这可能是一个通用的面向对象编程问题。我想进行关于接口和抽象类在使用上的通用比较。
什么时候应该使用接口,什么时候应该使用抽象类?
这可能是一个通用的面向对象编程问题。我想进行关于接口和抽象类在使用上的通用比较。
什么时候应该使用接口,什么时候应该使用抽象类?
抽象类可以拥有共享的状态或功能。接口仅是提供状态或功能的承诺。良好的抽象类能够减少需要重新编写的代码量,因为它的功能或状态可以被共享。而接口没有定义任何信息可供共享。
就我个人而言,我几乎从来没有写过抽象类。
大多数情况下,我看到抽象类被滥用,是因为抽象类的作者使用了“模板方法”模式。
“模板方法”的问题在于它几乎总是有点可重入 - “派生”类不仅知道它正在实现的基类的“抽象”方法,还知道基类的公共方法,尽管大部分时间它不需要调用它们。
(过度简化的)示例:
abstract class QuickSorter
{
public void Sort(object[] items)
{
// implementation code that somewhere along the way calls:
bool less = compare(x,y);
// ... more implementation code
}
abstract bool compare(object lhs, object rhs);
}
这里,这个类的作者编写了一个通用算法,并希望人们通过提供自己的"钩子"(在这种情况下为"compare"方法)来对其进行"特化"以便使用它。因此,预期的用法类似于:class NameSorter : QuickSorter
{
public bool compare(object lhs, object rhs)
{
// etc.
}
}
这样做的问题在于您过度耦合了两个概念:interface IComparator
{
bool compare(object lhs, object rhs);
}
class QuickSorter
{
private readonly IComparator comparator;
public QuickSorter(IComparator comparator)
{
this.comparator = comparator;
}
public void Sort(object[] items)
{
// usual code but call comparator.Compare();
}
}
class NameComparator : IComparator
{
bool compare(object lhs, object rhs)
{
// same code as before;
}
}
现在请注意:我们拥有的全部是接口和这些接口的具体实现。实际上,你不需要其他任何东西来进行高级面向对象设计。
为了“隐藏”我们通过使用“QuickSort”类和“NameComparator”实现了“姓名排序”的事实,我们可能仍然会在某个地方编写工厂方法:
ISorter CreateNameSorter()
{
return new QuickSorter(new NameComparator());
}
任何时候你有一个抽象类,你都可以这样做...即使在基类和派生类之间存在自然的可重入关系时,通常也值得将它们显式化。
最后一点思考:我们所做的只是通过使用 "QuickSort" 函数和 "NameComparison" 函数来“组合”一个“NameSorting”函数...在函数式编程语言中,这种编程风格变得更加自然,代码更少。
interface
和abstract
class之间的主要区别。Serializable
接口。Reader
。FileReader是一个Reader
FileReader
和BufferedReader
用于读取数据的共同目的,并且它们通过Reader
类相关联。
接口(具有能力的接口)
Serializable是一个接口。
假设您的应用程序中有两个实现Serializable
接口的类
Employee implements Serializable
Game implements Serializable
在这里,您无法通过Serializable
接口在Employee
和Game
之间建立任何关系,因为它们的目的不同。两者都能够序列化状态,但比较到此结束。
看一下这些帖子:
我的观点:
接口基本上定义了一个合同,任何实现该接口的类必须遵守(实现接口成员),它不包含任何代码。
另一方面,抽象类可以包含代码,并且可能有一些标记为抽象的方法,继承类必须实现这些方法。
我使用抽象类的罕见情况是当我有一些默认功能时,继承类可能没有兴趣覆盖,在抽象基类中,某些专业类继承自此基类。
例如(非常简单的例子!):考虑一个名为Customer的基类,其中包含抽象方法如CalculatePayment()
,CalculateRewardPoints()
,以及一些非抽象方法如GetName()
,SavePaymentDetails()
。
像RegularCustomer
和GoldCustomer
这样的专业类将从Customer
基类继承并实现自己的CalculatePayment()
和CalculateRewardPoints()
方法逻辑,但重新使用GetName()
和SavePaymentDetails()
方法。
您可以向抽象类添加更多功能(非抽象方法),而不会影响使用旧版本的子类。而向接口添加方法会影响实现它的所有类,因为它们现在需要实现新添加的接口成员。
所有成员都是抽象的抽象类类似于接口。
好的,我刚“领悟”了这个问题 - 这里是通俗易懂的解释(如果我理解有误请纠正)- 我知道这个话题很老了,但是未来可能还有其他人会遇到类似的问题...
抽象类允许你创建一个蓝图,并且允许你构造(实现)你想要所有子类都拥有的属性和方法。
另一方面,接口只允许你声明在所有实现它的类中希望存在具有给定名称的属性和/或方法 - 但不指定如何实现它。此外,一个类可以实现多个接口,但只能扩展一个抽象类。接口更像是一个高层次的架构工具(如果你开始掌握设计模式,就会更清楚) - 抽象类在两个方面都有所涉足,也可以执行一些琐碎的工作。
为什么要使用其中之一?前者允许对后代进行更具体的定义,而后者允许更大程度上的多态性。这最后一点对于最终用户/编码者非常重要,他们可以利用这些信息来实现A.P.(接口)以适应各种组合/形状的需求。
我认为这是我的“灯泡瞬间” - 少从作者的角度考虑接口,更多地从后来在项目中添加实现或扩展API的任何编码器的角度考虑接口。
如果你的概念清晰,那么在什么时候做什么是一件非常简单的事情。
抽象类可以派生出子类,而接口只能被实现。这两者之间存在一些区别。当你派生一个抽象类时,派生类和基类之间的关系是"是一个"的关系。例如,狗是动物,羊也是动物,这意味着派生类继承了一些来自基类的属性。
而对于接口的实现,关系则是"可以是"。例如,狗可以是间谍狗,狗可以是马戏团狗,狗可以是赛跑狗。这意味着你通过实现特定的方法来获得某些东西。
希望我表达清楚。
何时优先选择抽象类而非接口?
何时优先选择接口而非抽象类?
1.如果您正在创建为无关类提供常见功能的内容,请使用接口。
2.如果您正在为在层次结构中紧密相关的对象创建内容,请使用抽象类。
类只能继承一个基类,因此如果您想使用抽象类为一组类提供多态性,则它们必须全部继承自该类。抽象类还可以提供已实现的成员。因此,您可以使用抽象类确保某些相同的功能,但不能使用接口。
以下是一些建议,以帮助您决定是使用接口还是抽象类来为您的组件提供多态性:
摘自:
http://msdn.microsoft.com/en-us/library/scsyfw1d%28v=vs.71%29.aspx