何时使用接口而不是抽象类,反之亦然?
这可能是一个通用的OOP问题。 我想根据用法在接口和抽象类之间进行通用比较。
什么时候想使用一个接口,什么时候会想要使用一个抽象类 ?
我写了一篇文章:
抽象类和接口
总结:
当我们谈论抽象类时,我们正在定义对象类型的特征; 指定一个对象是什么 。
当我们谈论一个接口并定义我们承诺提供的功能时,我们正在讨论建立一个关于该对象可以做什么的合同。
抽象类可以具有共享状态或功能。 接口只是提供状态或功能的承诺。 一个好的抽象类将减少必须重写的代码量,因为它的功能或状态可以共享。 界面没有定义的信息要共享
就我个人而言,我几乎从不需要编写抽象类。
大多数时候我看到抽象类被(错误)使用,这是因为抽象类的作者正在使用“模板方法”模式。
“模板方法”的问题是它几乎总是有些重入 - “派生”类不仅知道它正在实现的基类的“抽象”方法,而且还知道基类的公共方法即使大多数时候不需要打电话给他们。
(过度简化)示例:
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);
}
所以在这里,这个类的作者写了一个通用算法,并打算让人们通过提供他们自己的“钩子”来“专门化”它 - 在这种情况下,“比较”方法。
所以预期的用法是这样的:
class NameSorter : QuickSorter
{
public bool compare(object lhs, object rhs)
{
// etc.
}
}
问题在于你不适当地将两个概念联系在一起:
在上面的代码中,理论上,“比较”方法的作者可以重新回到超类“排序”方法中......尽管在实践中他们将永远不想或不需要这样做。
您为这种不需要的耦合付出的代价是很难更改超类,而且在大多数OO语言中,不可能在运行时更改超类。
另一种方法是使用“策略”设计模式:
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;
}
}
所以现在注意:我们所有的都是接口,以及这些接口的具体实现。 在实践中,你并不需要其他任何东西来进行高级OO设计。
为了“隐藏”我们通过使用“QuickSort”类和“NameComparator”实现“排序名称”的事实,我们仍然可以在某处编写一个工厂方法:
ISorter CreateNameSorter()
{
return new QuickSorter(new NameComparator());
}
每当你有一个抽象类时,你都可以做到这一点......即使在基类和派生类之间存在一种自然的可重入关系时,通常也会使它们变得明确。
最后一个想法:我们上面所做的全部工作是通过使用“QuickSort”函数和“NameComparison”函数“编写”一个“NameSorting”函数......在功能性编程语言中,这种编程风格变得更加自然,用较少的代码。
链接地址: http://www.djcxy.com/p/38137.html上一篇: When to use an interface instead of an abstract class and vice versa?