Составной шаблон в C ++ и C # — защищенные виртуальные методы

Как добавить защищенный виртуальный метод в класс «Компонент», чтобы его можно было вызывать из «Композит»?

В качестве конкретного примера, посмотрите на код ниже, и, пожалуйста, скажите мне, как избежать ошибки компилятора в 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
}
}

РЕДАКТИРОВАТЬ: я изменил свой образец, поэтому у меня есть ComputeSize вместо Init (люди предполагают, что Init всегда можно вызвать в конструкторе).

2

Решение

Создать не виртуальную функцию Initialise() в базовом классе, который вызывает Init

например:

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

Как указано в комментариях ниже, Initialise должен быть открыт или статичен (только в C #), он может оставаться защищенным в C ++.
В C ++ вы можете сделать Init частным и получать к нему доступ только через вызовы Initialise, Смотрите не виртуальный интерфейс http://en.wikipedia.org/wiki/Non-virtual_interface_pattern

1

Другие решения

Ты не можешь Защищенный член другого объекта может быть вызван только в том случае, если компилятор видит, что рассматриваемый объект того же типа, что и ваш текущий объект. По сути, «защищенный» означает, что «производные классы могут использовать этот член в своем собственном классе.

Основная проблема здесь заключается в том, что вы хотите, чтобы некоторые привилегированные классы («композиты») могли вызывать метод внешних классов («компонентов»), который базовый класс объявляет только для использования производных классов в их собственной реализации.

Вы можете сделать Init внутренний, если все композиты находятся в одном пакете. Или может сделать подкласс компонента, который наследуют все композиты, и сделать этот конкретный класс привилегированным для вызова Init на все компоненты. В C ++ вы бы делали это с объявлениями друзей. В C # осторожное использование внутреннего доступа, вероятно, является правильным решением.

2

По вопросам рекламы [email protected]