Mul*_*der 5 c# abstract-class abstract-methods
我想知道两个约定之间的区别:
有什么不同?
Mat*_*ott 10
与接口非常相似,抽象类旨在为您的类型表达一组已知操作.但是,与接口不同,抽象类允许您实现可由任何派生类型使用的公共/共享功能.例如:
public abstract class LoggerBase
{
public abstract void Write(object item);
protected virtual object FormatObject(object item)
{
return item;
}
}
Run Code Online (Sandbox Code Playgroud)
在上面这个非常基本的例子中,我基本上做了两件事:
鉴于我知道任何派生类型LoggerBase将有一个Write方法,我可以称之为.以上作为接口的等价物可以是:
public interface ILogger
{
void Write(object item);
}
Run Code Online (Sandbox Code Playgroud)
作为一个抽象类,我可以提供一个额外的服务FormatObject,可以选择覆盖,比如我写的是ConsoleLogger,例如:
public class ConsoleLogger : LoggerBase
{
public override void Write(object item)
{
Console.WriteLine(FormatObject(item));
}
}
Run Code Online (Sandbox Code Playgroud)
通过将FormatObject方法标记为虚拟,这意味着我可以提供共享实现.我也可以覆盖它:
public class ConsoleLogger : LoggerBase
{
public override void Write(object item)
{
Console.WriteLine(FormatObject(item));
}
protected override object FormatObject(object item)
{
return item.ToString().ToUpper();
}
}
Run Code Online (Sandbox Code Playgroud)
所以,关键部分是:
abstract 类必须继承.abstract 方法必须在派生类型中实现.virtual 方法可以在派生类型中重写.在第二种情况下,因为您不会将功能添加到抽象基类,所以在直接处理基类的实例时无法调用该方法.例如,如果我实施ConsoleLogger.WriteSomethingElse,我无法从中调用它LoggerBase.WriteSomethingElse.
将抽象方法放在基类中然后在子类中实现它们的想法是,您可以使用父类型而不是任何特定的子类。例如,说您要对数组进行排序。您可以将基类定义为类似
abstract class Sorter {
public abstract Array sort(Array arr);
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以在子类中实现各种算法,例如quicksort,mergesort,heapsort。
class QuickSorter {
public Array sort(Array arr) { ... }
}
class MergeSorter {
public Array sort(Array arr) { ... }
}
Run Code Online (Sandbox Code Playgroud)
您可以通过选择算法来创建排序对象,
Sorter sorter = QuickSorter();
Run Code Online (Sandbox Code Playgroud)
现在,您可以通过sorter,而无需揭露它是快速分类的事实。你说要对数组排序
Array sortedArray = sorter.sort(someArray);
Run Code Online (Sandbox Code Playgroud)
这样,实现的细节(使用哪种算法)就从接口与对象分离(它对数组进行排序的事实)。
一个具体的优点是,如果您希望在某个时候使用不同的排序算法,则可以在单行中QuickSort()改为说MergeSort,而无需在其他任何地方进行更改。如果sort()父级中不包含方法,则QuickSorter每次调用时都必须向下转换sort(),然后更改算法将更加困难。