抽象 class 中的受保护抽象或 public 抽象方法

Protected abstract or public abstract method in abstract class

您好,我有一个抽象 class,其中有一些 public 方法和一些抽象方法。 我有 public 以便他们为派生的 classes 实现通用方法。

令我困惑的是为什么我要定义一个 public 抽象方法而不是受保护的抽象方法。在抽象 class 中定义一个 public 抽象方法对我来说毫无意义。因为如果是一个抽象将被覆盖,在派生的 classes 中,但相同的是if 被定义为 public 但不知何故将其定义为受保护更有意义,因为我们知道我们将在派生的 classes.

中覆盖它

在一个抽象class中把方法定义为public抽象是不是错了?哪个更好,为什么?

出于同样的原因,您希望在对象中使用 public 方法 :) 您只是不知道现阶段的具体实施。 它在 类 中很常见,具有非常高的抽象级别,例如中间件。

编辑:100% 合法。您只需要确保它是您希望在每个具体实现中向世界其他地方公开的功能。入口点方法(例如:start、execute、parse..)通常属于此类。

抽象 Class 本身必须与继承自它的 Classes 一样易于访问。因此,如果继承的 Class 是 Public,那么抽象 Class 也必须是 public。

Public Abstract 与其他 Public 方法具有相同的 Idea:如果您有 Abstract Class,您将通过此 arround。因此,如果应该从外部调用此方法,则为 public。如果该方法仅用于 Child 和 Parent 之间的通信,那么 protected 是可行的方法。简单示例,将 Main-Method 视为抽象 class:

的用户
    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");
        }
    }

这取决于你想达到什么目的。例如,您有一个 Television class,它有 3 个方法,TurnOnTurnOffDraw.

您只希望客户 TurnOnTurnOff 电视,但只有其子 class 应该知道屏幕上的内容和方式 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.
    }
}

客户可以 TurnOnTurnOff 电视,但不能 Draw 屏幕上的任何内容。

TLTR:因为开闭原则

为什么使用抽象成员 protected 而不是 public 是有意义的,据我所知,隐藏“实现细节”。如果要确保 保留在 class 中定义每个抽象成员的意图,公开一个“入口点”很方便。通常,public 方法将协调何时调用或访问什么抽象成员,以及在什么情况下以什么特定顺序调用,但是 封装层 [=42= 的权衡] 是你失去了 扩展性 属性.

解释:

假设我们创建一个包含多个异常处理程序的库 classes.

初步实施:

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...
            inner: 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 _base;

    public ExceptionHandlerWrapper(ExceptionHandlerBase @base)
    {
        thos._base = @base;
    }

    protected override void HandleException(Exception ex, Action operation)
    {
        this.BeforeHandleException();
        this._base.HandleException(ex, operation); // Compile error**
    }
    
    private void BeforeHandleException()
    {
        // do additional stuff
    }
}

如您所见,存在编译错误,因为无法从定义它的class 外部访问ExceptionHandlerBase.HandleException