这可能是一个通用的OOP问题。我想在接口和抽象类的使用基础上做一个通用的比较。
什么时候需要使用接口,什么时候需要使用抽象类?
这可能是一个通用的OOP问题。我想在接口和抽象类的使用基础上做一个通用的比较。
什么时候需要使用接口,什么时候需要使用抽象类?
当前回答
两者都是类定义的契约:
结论1:两种意图都是对象泛化
在定义抽象类时,它们也可以有默认实现。
结论2:区分存在于行为泛化设计中
在使用抽象类时,类只能从一个抽象类继承
结论3:抽象类在应用上存在局限性。它的意思是 行为概括的局限性。
最后结论-何时使用哪个:区分是在行为泛化层面
在类的行为设计中,如果功能在确定的类之间只是概念上的限制,换句话说,在确定的类之间是共享的,则使用抽象类。但如果功能比确定类更通用,或者我们可以/想要向其他类添加功能,则使用接口作为契约。
其他回答
我写过一篇关于何时使用抽象类和何时使用接口的文章。除了“一个是a……”之外,他们之间还有很多不同之处。一个能做……”。对我来说,这些都是事先准备好的答案。我提到了使用它们中的任何一种的一些原因。希望能有所帮助。
http://codeofdoom.com/wordpress/2009/02/12/learn-this-when-to-use-an-abstract-class-and-an-interface/
如果我们有一个对所有派生类都相同的实现,那么此时最好使用抽象类而不是接口。当我们有一个接口时,我们可以将我们的实现移动到任何实现接口的类。在抽象类中,它避免了代码重复,并共享所有派生类的实现。接口允许开发松散耦合的系统,这有助于更好的测试。
1.如果您正在创建为不相关的类提供公共功能的东西,请使用接口。
2.如果您正在为层次结构中密切相关的对象创建一些东西,请使用抽象类。
如果你认为java是面向对象语言,
“接口不提供方法实现”在Java 8启动后不再有效。现在java为默认方法提供了接口实现。
简单来说,我想用
接口:通过多个不相关的对象实现一个契约。它提供了“HAS A”功能。
抽象类:在多个相关对象之间实现相同或不同的行为。它建立了“IS A”关系。
Oracle网站提供了接口和抽象类之间的关键区别。
考虑使用抽象类,如果:
您希望在几个密切相关的类之间共享代码。 您希望扩展抽象类的类具有许多公共方法或字段,或者需要除public以外的访问修饰符(例如protected和private)。 您希望声明非静态或非final字段。
考虑使用接口,如果:
您希望不相关的类实现您的接口。例如,许多不相关的对象都可以实现Serializable接口。 您希望指定特定数据类型的行为,但不关心由谁实现其行为。 您希望利用类型的多重继承。
例子:
抽象类(IS一个关系)
Reader是一个抽象类。
BufferedReader是一个Reader
FileReader是一个阅读器
FileReader和BufferedReader用于一个共同的目的:读取数据,它们通过Reader类相互关联。
接口(具有功能)
Serializable是一个接口。
假设您的应用程序中有两个实现Serializable接口的类
Employee实现Serializable
游戏实现Serializable
在这里,你不能通过Serializable接口在员工和游戏之间建立任何关系,这是为了不同的目的。两者都能够序列化状态,比较到此结束。
看看这些帖子:
我应该如何解释接口和抽象类之间的区别?
我认为最简洁的说法是:
共享属性=>抽象类。 共享功能=>接口。
更简单地说……
抽象类示例:
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发出声音,但是我们还不知道它的实现。在这种情况下,我们可以抽象接口实现并将其实现委托给它的子类。
最后一点,还记得在抽象类示例中我们如何操作不同对象的共享属性,以及在接口示例中我们如何调用不同对象的共享功能吗?在最后一个例子中,我们可以两者都做。