Frage

How can I add a protected virtual method in the "Component" class, so that it can be called from the "Composite"?

As an concrete example, look at the code below, and please tell me how to avoid the compiler error in DxCompositeShape.ComputeSize.

abstract class DxShape // this is the Component
{
    public abstract void Paint();
    protected abstract void ComputeSize();
}

class DxCompositeShape : DxShape // this is the Composite
{
    public readonly IList<DxShape> Shapes = new List<DxShape>();

    public override void Paint()
    {
        this.ComputeSize();
    }

    protected override void ComputeSize()
    {
        foreach (DxShape sh in Shapes)
        {
            sh.ComputeSize(); // compiler error CS1540
        }
        // and some other logic here
    }
}

EDIT: I modified my sample, so I have ComputeSize instead of Init (people assume that Init can always be called in a constructor).

War es hilfreich?

Lösung 2

Create a non-virtual function Initialise() in the base class that calls Init

eg:

abstract class DxShape
{
    protected void Initialise()
    {
        Init();
    }
    protected abstract void Init();
    //...
}

As pointed out in the comments below, Initialise must be made either public or static (only in C#), it may remain protected in C++. In C++ you could then make Init private and only access it via calls to Initialise. See non-virtual interface http://en.wikipedia.org/wiki/Non-virtual_interface_pattern

Andere Tipps

You can't. A protected member of a different object can only be invoked if the compiler can see that the object in question is of the same type as your current object. Basically, "protected" means "Derived classes can use this member in their own class.

The underlying issue here is that you want some privileged classes ("composites") to be able to call a method of foreign classes ("components") that the base class declares is only for use of derived classes in their own implementation.

You might want to make Init internal, if all composites are in the same package. Or maybe make a subclass of the component that all composites inherit, and make this particular class privileged to call Init on all components. In C++ you would do such a thing with friend declarations. In C#, careful use of internal access is probably the right solution.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top