我正在研究一些抽象概念,并想知道抽象类是否应该直接实现接口,或者你应该扩展类并在子类型中实现接口。
所以在下面的例子中:
interface Being{
alive:boolean;
}
abstract class Animal implements Being{
alive:boolean;
}
class Dog extends Animal{
bark(){
console.log("Bark");
}
}
class Earth{
beings:Being[];
}
该示例可以重写如下所示:
interface Being{
alive:boolean;
}
abstract class Animal{
alive:boolean;
}
class Dog extends Animal implements Being{
bark(){
console.log("Bark");
}
}
class Earth{
beings:Being[];
}
我的问题是:
答案 0 :(得分:1)
您可以更进一步,根本不需要实现接口,因为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()]
}
显式实现接口的好处是你在类声明站点上得到错误,而不是在类使用站点上。
关于问题的主要部分,您应该将implements
放在实际执行的类上。如果abstract
类实现了接口的所有成员,那么最好将implements
放在那里。如果您的抽象类没有实现所有方法,并且您希望某些派生类不需要实现该接口,那么将implements
放在需要实现该接口的特定类上。
答案 1 :(得分:1)
嗯,我觉得你有点给自己答案。这两个例子代表了不同的用例,所以我认为没有一个“更好的例子”。
让我们尝试将其分解为简单的词语。
第一个例子,你有一个存在,所有动物明确地拥有属性“活着”。在这个例子中,这也适用于狗。
在第二个示例中,您的Animal不需要具有“alive”属性。 (那么问题是,如果真的有意义的话)。然而,Dog再次实现了界面。
所以,如果你说有可能有一只狗,那就是动物,但不应该有“活着”属性(也许它是一只僵尸狗)你应该把它放在狗身上。但是如果你要将所有字段/函数/逻辑实现到Animal类中(并且你不关心Zombie-Dogs),你应该将接口放在Animal类上。
所以这可能不是你想要的“明确”答案。但这取决于具体情况。您应该始终在相应逻辑所在的位置实现接口。因此,如果你想让活着的逻辑在动物身上放在那里,如果有动物没有活着的属性,就把它放在狗身上。