抽象 class 是否应该直接实现接口。有什么优点和缺点
Should an abstract class implement interfaces directly. What are the advantages and disadvantages
我正在研究抽象的一些概念,想知道抽象 class 是否应该直接实现接口,或者您应该扩展 class 并在子类型中实现接口。
所以在下面的例子中:
- 不再冗长
- 动物可以直接作为地球
中生物的类型
interface Being{
alive:boolean;
}
abstract class Animal implements Being{
alive:boolean;
}
class Dog extends Animal{
bark(){
console.log("Bark");
}
}
class Earth{
beings:Being[];
}
示例可以重写如下所示:
- 它更详细,你可以看到 Dog 实现了 Being 接口
interface Being{
alive:boolean;
}
abstract class Animal{
alive:boolean;
}
class Dog extends Animal implements Being{
bark(){
console.log("Bark");
}
}
class Earth{
beings:Being[];
}
我的问题是:
- 第二个例子更好吗?
- 我们需要更高版本的示例是什么?
- 高版本有什么优势?
你可以走得更远,你根本不需要实现接口,因为 typescript 使用结构兼容性来确定类型兼容性。例如这个编译:
interface Being {
alive: boolean;
}
abstract class Animal {
alive: boolean = true;
}
class Dog extends Animal {
bark() {
console.log("Bark");
}
}
class Earth {
beings: Being[] = [new Dog()]
}
显式实现接口的优点是您会在 class 声明位置得到错误,而不是仅在 class 使用位置得到错误。
关于您问题的主要部分,您应该将 implements
放在实际执行的 class 上。如果 abstract
class 实现接口的所有成员,最好将 implements
放在那里。如果你的抽象class没有实现所有的方法,而你期望一些派生的classes不需要实现接口,那么把implements
放在具体的class上需要实现接口的es.
好吧,我想你已经给了自己答案。这两个示例代表不同的用例,所以我认为没有 "better example".
让我们试着把它分解成简单的单词。
第一个例子,你有一个存在,所有动物都明确地具有属性 "alive"。在此示例中,这也适用于 Dog。
然而,在第二个示例中,您的 Animal 不需要具有 "alive" 属性。 (那么问题是,拥有它是否真的有意义)。然而 Dog 再次实现了接口。
所以如果你说有可能有一只狗,那是一只动物但不应该有属性 "alive"(也许是 Zombie-Dog)你应该把它放在狗身上本身。但是如果你打算将所有 fields/functions/logic 实现到 Animal class 中(并且你不关心 Zombie-Dogs)你应该把接口放在 Animal class.
所以这可能不是您正在寻找的 "clear" 答案。但这要视情况而定。您应该始终在相应逻辑所在的位置实现接口。所以如果你想让活着的逻辑在动物身上,把它放在那里,如果可以有没有活着的动物属性,把它放在狗身上。
我正在研究抽象的一些概念,想知道抽象 class 是否应该直接实现接口,或者您应该扩展 class 并在子类型中实现接口。
所以在下面的例子中:
- 不再冗长
- 动物可以直接作为地球 中生物的类型
interface Being{
alive:boolean;
}
abstract class Animal implements Being{
alive:boolean;
}
class Dog extends Animal{
bark(){
console.log("Bark");
}
}
class Earth{
beings:Being[];
}
示例可以重写如下所示:
- 它更详细,你可以看到 Dog 实现了 Being 接口
interface Being{
alive:boolean;
}
abstract class Animal{
alive:boolean;
}
class Dog extends Animal implements Being{
bark(){
console.log("Bark");
}
}
class Earth{
beings:Being[];
}
我的问题是:
- 第二个例子更好吗?
- 我们需要更高版本的示例是什么?
- 高版本有什么优势?
你可以走得更远,你根本不需要实现接口,因为 typescript 使用结构兼容性来确定类型兼容性。例如这个编译:
interface Being {
alive: boolean;
}
abstract class Animal {
alive: boolean = true;
}
class Dog extends Animal {
bark() {
console.log("Bark");
}
}
class Earth {
beings: Being[] = [new Dog()]
}
显式实现接口的优点是您会在 class 声明位置得到错误,而不是仅在 class 使用位置得到错误。
关于您问题的主要部分,您应该将 implements
放在实际执行的 class 上。如果 abstract
class 实现接口的所有成员,最好将 implements
放在那里。如果你的抽象class没有实现所有的方法,而你期望一些派生的classes不需要实现接口,那么把implements
放在具体的class上需要实现接口的es.
好吧,我想你已经给了自己答案。这两个示例代表不同的用例,所以我认为没有 "better example".
让我们试着把它分解成简单的单词。
第一个例子,你有一个存在,所有动物都明确地具有属性 "alive"。在此示例中,这也适用于 Dog。
然而,在第二个示例中,您的 Animal 不需要具有 "alive" 属性。 (那么问题是,拥有它是否真的有意义)。然而 Dog 再次实现了接口。
所以如果你说有可能有一只狗,那是一只动物但不应该有属性 "alive"(也许是 Zombie-Dog)你应该把它放在狗身上本身。但是如果你打算将所有 fields/functions/logic 实现到 Animal class 中(并且你不关心 Zombie-Dogs)你应该把接口放在 Animal class.
所以这可能不是您正在寻找的 "clear" 答案。但这要视情况而定。您应该始终在相应逻辑所在的位置实现接口。所以如果你想让活着的逻辑在动物身上,把它放在那里,如果可以有没有活着的动物属性,把它放在狗身上。