繁体   English   中英

抽象类中受保护的抽象或公共抽象方法

[英]Protected abstract or public abstract method in abstract class

嗨,我有一个抽象类,其中有一些公共方法和一些抽象方法。 我有公众,以便他们实现派生类的通用方法。

令我困惑的是为什么我要定义一个公共抽象方法而不是受保护的抽象方法。 在抽象类中定义公共抽象方法对我来说没有任何意义......因为在派生类中 if 是一个抽象将被覆盖,但同样是 if 被定义为公共但不知何故定义更有意义正如我们所知,它受到保护,我们将在派生类中覆盖它。

在抽象类中将方法定义为公共抽象是错误的吗? 哪个更好?为什么?

这取决于你想要达到的目标。 例如,你有一个拥有3种方法的Television类, TurnOnTurnOffDraw

您只希望客户使用TurnOnTurnOff电视,但只有其子类应该知道在屏幕上Draw什么以及如何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任何东西。

出于同样的原因,你想要一个对象中的公共方法:)你只是不知道这个阶段的特定实现。 它在具有非常高抽象级别的类中很常见,例如中间件。

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

UML抽象公共考试

Abstract Class本身必须像继承它的Classes一样可访问。 因此,如果继承的Classes是Public,则Abstract Class也必须是公共的。

Public Abstract与其他公共方法具有相同的想法:如果你有一个抽象类,你将传递这个arround。 因此,如果此方法应该从外部调用,那么它是公开的。 如果该方法仅用于Child和Parent之间的通信,则受保护是可行的方法。 简单的示例,请参阅Main-Method作为抽象类的用户:

    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:因为开闭原则

解释:

假设我们创建了一个包含多个异常处理程序类的库。

初步实施:

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: ProcessHandlerBase
{
    protected override void HandleException(Exception ex, Action operation)
    {
        throw new Exception(
            message: "Wrong input"   // or whatever...
            inner: ex);
    }
}

public class DbExceptionHandler : ProcessHandlerBase
{
    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 ExceptionHandlerFacade : ExceptionHandlerBase
{
    readonly ExceptionHandlerBase _base;

    public ExceptionHandlerFacade(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
    }
}

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


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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM