简体   繁体   English

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

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

Hi I have an abstract class in which I have some public methods and some abstract ones.嗨,我有一个抽象类,其中有一些公共方法和一些抽象方法。 I have the public so that they implement the common methods for the derived classes.我有公众,以便他们实现派生类的通用方法。

What is confusing me is why I will want to define a public abstract method instead of protected abstract.令我困惑的是为什么我要定义一个公共抽象方法而不是受保护的抽象方法。 That makes no sense to me to define a public abstract method in abstract class.... because if is an abstract will be overridden, in the derived classes, but the same is if is defined as public but somehow it makes more sense to define it as protected as we know that we will override that in the derived classes.在抽象类中定义公共抽象方法对我来说没有任何意义......因为在派生类中 if 是一个抽象将被覆盖,但同样是 if 被定义为公共但不知何故定义更有意义正如我们所知,它受到保护,我们将在派生类中覆盖它。

Is it wrong to define the method as public abstract in an abstract class?在抽象类中将方法定义为公共抽象是错误的吗? Which is better and why?哪个更好?为什么?

It depends on what you want to achieve. 这取决于你想要达到的目标。 For example, you have a Television class that has 3 methods, TurnOn , TurnOff , and Draw . 例如,你有一个拥有3种方法的Television类, TurnOnTurnOffDraw

You only want clients to TurnOn or TurnOff the TV but only its subclass should know what and how to Draw on the screen. 您只希望客户使用TurnOnTurnOff电视,但只有其子类应该知道在屏幕上Draw什么以及如何Draw So, Television will look more or less like below. 因此, Television看起来或多或少会像下面一样。

public abstract class Television
{
    public abstract void TurnOn();

    public abstract void TurnOff();

    protected abstract void Draw();
}

Then each company has its own implementation. 然后每个公司都有自己的实施。

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.
    }
}

Clients can TurnOn or TurnOff a TV but cannot Draw anything on the screen. 客户可以TurnOnTurnOff电视,但不能在屏幕上Draw任何东西。

For the same reason you want a public method in an object :) You just don't know the particular implementation at this stage. 出于同样的原因,你想要一个对象中的公共方法:)你只是不知道这个阶段的特定实现。 It is common in classes with very high level of abstraction, middlewares for example. 它在具有非常高抽象级别的类中很常见,例如中间件。

Edit: It is 100% legal. 编辑:这是100%合法。 You just need to be sure that it is functionality that you want to expose to the rest of the world in every concrete implementation. 您只需要确保它是您希望在每个具体实现中向世界其他地方公开的功能。 Entry point methods (ex: start, execute, parse..) are usually of this kind. 入口点方法(例如:start,execute,parse ..)通常属于这种类型。

UML抽象公共考试

The Abstract Class itself has to be as accessible as the Classes, which inherit from it. Abstract Class本身必须像继承它的Classes一样可访问。 So if the inherited Classes are Public, the Abstract Class has to be public too. 因此,如果继承的Classes是Public,则Abstract Class也必须是公共的。

Public Abstract has the same Idea like other Public Methods: If you have a Abstract Class, you will pass this arround. Public Abstract与其他公共方法具有相同的想法:如果你有一个抽象类,你将传递这个arround。 So if this Method should get called from outside, it's public. 因此,如果此方法应该从外部调用,那么它是公开的。 If the method is just for communication between Child and Parent, protected is the way to go. 如果该方法仅用于Child和Parent之间的通信,则受保护是可行的方法。 Easy example, see the Main-Method as the user of the abstract class: 简单的示例,请参阅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: because of Open-Close principle . TLTR:因为开闭原则

Explanation:解释:

Suppose we create a library with multiple exception handler classes.假设我们创建了一个包含多个异常处理程序类的库。

Initial implementation:初步实施:

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();
    }
}

Now, if we want to extend the behavior of ExceptionHandlerBase we will see that we are limited because of that protected access modifier of ExceptionHandlerBase.HandleException method.现在,如果我们想扩展ExceptionHandlerBase的行为,我们将看到由于ExceptionHandlerBase.HandleException方法的protected访问修饰符而受到限制。

Let's try to add a hook before ExceptionHandlerBase.HandleException method:让我们尝试在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
    }
}

As you can see, there is a compilation error because ExceptionHandlerBase.HandleException is not accessible from outside the class that defines it.如您所见,存在编译错误,因为无法从定义它的类外部访问ExceptionHandlerBase.HandleException


Why it makes sense to have abstract members protected instead of public is, from what I can see, to hide "implementation details".从我所见,为什么让抽象成员protected而不是public是有意义的,以隐藏“实现细节”。 It is convenient to expose one single "entry point" if you want to ensure that the intent of which each abstract member is defined inside the class is preserved.如果要确保保留在类中定义每个抽象成员的意图,则公开一个“入口点”很方便。 Normally, it is the public method which will orchestrate when and what abstract members are called or accessed and in what particular order and under what circumstances, but the tradeoff for this layer of encapsulation is that you lose the extensibility property .通常,公共方法将协调何时以及什么抽象成员被调用或访问,以及在什么特定的顺序和在什么情况下,但是这一层封装的权衡是你失去了可扩展性属性

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

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