这可能是一个通用的OOP问题。我想在接口和抽象类的使用基础上做一个通用的比较。
什么时候需要使用接口,什么时候需要使用抽象类?
这可能是一个通用的OOP问题。我想在接口和抽象类的使用基础上做一个通用的比较。
什么时候需要使用接口,什么时候需要使用抽象类?
当前回答
类只能继承自一个基类,因此如果您想使用抽象类为一组类提供多态性,它们必须全部继承自该类。抽象类也可以提供已经实现的成员。因此,您可以使用抽象类确保一定数量的相同功能,但不能使用接口。
下面是一些建议,可以帮助您决定是使用接口还是抽象类为组件提供多态性。
If you anticipate creating multiple versions of your component, create an abstract class. Abstract classes provide a simple and easy way to version your components. By updating the base class, all inheriting classes are automatically updated with the change. Interfaces, on the other hand, cannot be changed once created in that way. If a new version of an interface is required, you must create a whole new interface. If the functionality you are creating will be useful across a wide range of disparate objects, use an interface. Abstract classes should be used primarily for objects that are closely related, whereas interfaces are best suited for providing common functionality to unrelated classes. If you are designing small, concise bits of functionality, use interfaces. If you are designing large functional units, use an abstract class. If you want to provide common, implemented functionality among all implementations of your component, use an abstract class. Abstract classes allow you to partially implement your class, whereas interfaces contain no implementation for any members.
抄袭: http://msdn.microsoft.com/en-us/library/scsyfw1d%28v=vs.71%29.aspx
其他回答
这是一个很难打的电话。
我可以给出一个提示:一个对象可以实现许多接口,而一个对象只能继承一个基类(在像c#这样的现代OO语言中,我知道c++有多个继承-但这不是不受欢迎吗?)
基本的经验法则是:对于“名词”使用抽象类,对于“动词”使用接口
例如:car是一个抽象类和驱动器,我们可以让它成为一个接口。
我认为最简洁的说法是:
共享属性=>抽象类。 共享功能=>接口。
更简单地说……
抽象类示例:
public abstract class BaseAnimal
{
public int NumberOfLegs { get; set; }
protected BaseAnimal(int numberOfLegs)
{
NumberOfLegs = numberOfLegs;
}
}
public class Dog : BaseAnimal
{
public Dog() : base(4) { }
}
public class Human : BaseAnimal
{
public Human() : base(2) { }
}
由于动物有一个共同的属性——在这种情况下是腿的数量——创建一个包含这个共同属性的抽象类是有意义的。这也允许我们编写操作该属性的通用代码。例如:
public static int CountAllLegs(List<BaseAnimal> animals)
{
int legCount = 0;
foreach (BaseAnimal animal in animals)
{
legCount += animal.NumberOfLegs;
}
return legCount;
}
接口的例子:
public interface IMakeSound
{
void MakeSound();
}
public class Car : IMakeSound
{
public void MakeSound() => Console.WriteLine("Vroom!");
}
public class Vuvuzela : IMakeSound
{
public void MakeSound() => Console.WriteLine("VZZZZZZZZZZZZZ!");
}
这里要注意的是,呜呜祖拉和汽车是完全不同的东西,但它们有共同的功能:发出声音。因此,接口在这里是有意义的。此外,它将允许程序员将发出声音的东西分组在一个公共界面下——在本例中是IMakeSound。通过这种设计,你可以编写以下代码:
List<IMakeSound> soundMakers = new List<ImakeSound>();
soundMakers.Add(new Car());
soundMakers.Add(new Vuvuzela());
soundMakers.Add(new Car());
soundMakers.Add(new Vuvuzela());
soundMakers.Add(new Vuvuzela());
foreach (IMakeSound soundMaker in soundMakers)
{
soundMaker.MakeSound();
}
你知道那会输出什么吗?
最后,您可以将两者结合起来。
结合例子:
public interface IMakeSound
{
void MakeSound();
}
public abstract class BaseAnimal : IMakeSound
{
public int NumberOfLegs { get; set; }
protected BaseAnimal(int numberOfLegs)
{
NumberOfLegs = numberOfLegs;
}
public abstract void MakeSound();
}
public class Cat : BaseAnimal
{
public Cat() : base(4) { }
public override void MakeSound() => Console.WriteLine("Meow!");
}
public class Human : BaseAnimal
{
public Human() : base(2) { }
public override void MakeSound() => Console.WriteLine("Hello, world!");
}
这里,我们要求所有的BaseAnimals发出声音,但是我们还不知道它的实现。在这种情况下,我们可以抽象接口实现并将其实现委托给它的子类。
最后一点,还记得在抽象类示例中我们如何操作不同对象的共享属性,以及在接口示例中我们如何调用不同对象的共享功能吗?在最后一个例子中,我们可以两者都做。
答案因语言而异。例如,在Java中,一个类可以实现(继承)多个接口,但只能继承一个抽象类。所以接口给了你更多的灵活性。但在c++中却不是这样。
我写过一篇关于何时使用抽象类和何时使用接口的文章。除了“一个是a……”之外,他们之间还有很多不同之处。一个能做……”。对我来说,这些都是事先准备好的答案。我提到了使用它们中的任何一种的一些原因。希望能有所帮助。
http://codeofdoom.com/wordpress/2009/02/12/learn-this-when-to-use-an-abstract-class-and-an-interface/