你什么时候使用其中一个?
public interface IFriendly
{
string GetFriendly();
}
public abstract class Person: IFriendly
{
public abstract string GetFriendly();
}
VS
public interface IFriendly
{
string GetFriendly();
}
public abstract class Person
{
// some other stuff i would like subclasses to have
}
public abstract class Employee : Person, IFriendly
{
public string GetFriendly()
{
return "friendly";
}
}
答案 0 :(得分:7)
嗯,你需要这样想:
public interface IBreathing
{
void Breathe();
}
//because every human breathe
public abstract class Human : IBreathing
{
abstract void Breathe();
}
public interface IVillain
{
void FightHumanity();
}
public interface IHero
{
void SaveHumanity();
}
//not every human is a villain
public class HumanVillain : Human, IVillain
{
void Breathe() {}
void FightHumanity() {}
}
//but not every is a hero either
public class HumanHero : Human, IHero
{
void Breathe() {}
void SaveHumanity() {}
}
关键是你的基类应该实现接口(或继承,但只将它的定义暴露为抽象),只有当从它派生的每个其他类也应该实现该接口时。
因此,通过上面提供的基本示例,只有每Human
次呼叫(这里正确)时,您才能IBreathing
实施Human
。
但是!您无法Human
同时IVillain
和IHero
,因为这会使我们以后无法区分它们是一个还是另一个。实际上,这样的实施意味着每个Human
都会立刻成为恶棍和英雄。
要结束问题的答案:
基类实现界面的缺点是什么?
没有,如果每个派生的类都应该实现该接口。
总是在子类上实现接口会更好吗?
如果从基础派生的每个类都应该实现该界面,那么必须
您何时使用其中一种?
如果从基类派生的每个类都应该实现这样的接口,那么make base class继承它。如果没有,请使具体类实现这样的接口。
答案 1 :(得分:2)
从基类开始将您绑定到基类的实现。我们总是开始认为基类正是我们想要的。然后我们需要一个新的继承类,它并不适合,所以我们发现自己回过头来修改基类以适应继承类的需要。它一直都在发生。
如果您从界面开始,那么您可以更灵活一点。您可以编写一个实现该接口的新类,而不必修改基类。你可以在它工作时获得类继承的好处,但是当它不起作用时你就不会与它联系在一起。
当我第一次使用OOP时,我喜欢类继承。令人惊讶的是,它最终变得不实用。这就是Composition Over Inheritance的主体所在的位置。它最好用类的组合来构建功能,而不是将它嵌套在继承的类中。
还有Open/Closed原则。如果你可以继承,那很好,但你不想回去改变基类(并冒险破坏其他东西),因为新的继承类需要正常工作。对接口而不是基类进行编程可以保护您不必修改现有的基类。