抽象类应该直接实现接口吗?有哪些优点和缺点

时间:2018-03-29 14:47:46

标签: javascript typescript abstraction

我正在研究一些抽象概念,并想知道抽象类是否应该直接实现接口,或者你应该扩展类并在子类型中实现接口。

所以在下面的例子中:

  • 它失去了冗长
  • 动物可以直接用作地球
  • 生物的类型
interface Being{
    alive:boolean;
}

abstract class Animal implements Being{
    alive:boolean;
}

class Dog extends Animal{
    bark(){
        console.log("Bark");
    }
}

class Earth{
    beings:Being[];
}

该示例可以重写如下所示:

  • 它更详细,您可以看到 Dog 实现存在界面
interface Being{
    alive:boolean;
}

abstract class Animal{
    alive:boolean;
}

class Dog extends Animal implements Being{
    bark(){
        console.log("Bark");
    }
}

class Earth{
    beings:Being[];
}

我的问题是:

  1. 第二个例子更好吗?
  2. 我们需要上层版本的例子是什么?
  3. 鞋面版有什么优点?

2 个答案:

答案 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类上。

所以这可能不是你想要的“明确”答案。但这取决于具体情况。您应该始终在相应逻辑所在的位置实现接口。因此,如果你想让活着的逻辑在动物身上放在那里,如果有动物没有活着的属性,就把它放在狗身上。

相关问题