你好,我有一个抽象类,在其中有一些公共方法和一些抽象方法。
我将这些公共方法放在里面是为了让它们实现派生类的公共方法。
我感到困惑的是,为什么我会希望定义一个公共抽象方法而不是受保护的抽象方法。在抽象类中定义一个公共抽象方法对我来说没有任何意义...因为如果是抽象的,那么它将在派生类中被重写,但是如果定义为公共的,那么在某种程度上将其定义为受保护的更有意义,因为我们知道我们将在派生类中重写它。
在抽象类中定义公共抽象方法是否有问题?哪个更好?为什么?
这取决于你想要实现什么。例如,你有一个名为Television
的类,它有3个方法:TurnOn
、TurnOff
和Draw
。
你只想让客户端TurnOn
或TurnOff
电视,但只有它的子类应该知道如何在屏幕上Draw
内容以及如何绘制。因此,Television
看起来会像下面这样。
public abstract class Television
{
public abstract void TurnOn();
public abstract void TurnOff();
protected abstract void Draw();
}
那么每个公司都有自己的实现方式。
public sealed class MyTelevision
: Television
{
public override void TurnOn()
{
Console.WriteLine("Turn on my tv");
}
public override void TurnOff()
{
Console.WriteLine("Turn off my tv");
}
protected override void Draw()
{
// code here.
}
}
客户可以打开
或关闭
电视,但不能在屏幕上画图
。
static void Main(string[] args)
{
Animal cat = new Cat();
Animal dog = new Dog();
cat.Eat();
dog.Eat();
cat.Move();
dog.Move();
}
public abstract class Animal
{
public abstract void Eat();
protected abstract void ComplexMoving();
public void Move()
{
ComplexMoving();
}
}
public class Dog : Animal
{
public override void Eat()
{
Debug.WriteLine("Dog says Namnam");
}
protected override void ComplexMoving()
{
Debug.WriteLine("Dog no stupid");
}
}
public class Cat: Animal
{
public override void Eat()
{
Debug.WriteLine("Cat says namnam");
}
protected override void ComplexMoving()
{
Debug.WriteLine("Cat does a slalom");
}
}
TLTR: 因为开闭原则。
为什么将抽象成员声明为protected
而非public
是有意义的呢?据我所见,这是为了隐藏实现细节。如果您想确保类内定义的每个抽象成员的意图被保留,公开一个单一的“入口点”很方便。通常像“Execute”、“Parse”、“Start”这样的方法就是这样的方法,就像@Sam Aleksov已经指出的那样。正是这些公共方法将协调何时以及在什么特定顺序和条件下调用或访问哪些抽象成员,但这种封装的代价是降低了扩展性。
假设我们创建了一个具有多个异常处理程序类的库。
初始实现:
namespace MyLibrary;
public abstract class ExceptionHandlerBase
{
protected abstract void HandleException(Exception ex, Action operation);
public void Execute(Action operation)
{
try {
operation.Invoke();
} catch(Exception ex) {
this.HandleException(ex, operation);
}
}
}
public class InputExceptionHandler: ExceptionHandlerBase
{
protected override void HandleException(Exception ex, Action operation)
{
throw new Exception(
message: "Wrong input", // or whatever...
innerException: ex);
}
}
public class DbExceptionHandler : ExceptionHandlerBase
{
protected override void HandleException(Exception ex, Action operation)
{
Console.WriteLine("Failed to connect to database. Retrying...");
operation. Invoke();
}
}
ExceptionHandlerBase
的行为,我们会发现由于 ExceptionHandlerBase.HandleException
方法的 protected
访问修饰符,我们受到了限制。ExceptionHandlerBase.HandleException
方法之前添加一个钩子:class ExceptionHandlerWrapper : ExceptionHandlerBase
{
readonly ExceptionHandlerBase _impl;
public ExceptionHandlerWrapper(ExceptionHandlerBase impl)
{
thos._impl= impl;
}
protected override void HandleException(Exception ex, Action operation)
{
this.BeforeHandleException();
this._impl.HandleException(ex, operation); // Compile error**
}
private void BeforeHandleException()
{
// do additional stuff
}
}
正如您所看到的,出现了编译错误,因为ExceptionHandlerBase.HandleException
无法从定义它的类外部访问。