Являются ли защищенные свойства злыми?

Вводный фрагмент кода:

class BaseClass
{
    protected Foo MyFoo { get; }
}

class ChildClass : BaseClass
{
    void SomeMethod()
    {
        MyFoo.DoStuff();
        //Here, I have no idea that MyFoo is not defined in this class,
        //but rather in the base class.
    }
}

Проблема/дискуссия заключается в том, что вам нужно либо знать, либо проверять вручную, где MyFoo определен. И вам лучше использовать два частных поля, один в базовом классе, в дочернем классе.

В нашем случае большую часть времени эти свойства поступают из инъекции зависимостей и доступны в конструктор обоих классов. Поэтому очень просто просто сопоставить их с частными свойствами из этого конструктора, а не наследовать его из базового класса, что также менее понятно.

Есть ли у меня хорошая практика? Какой у вас там опыт?

Основной вопрос. Являются ли защищенные свойства просто плохой привычкой, и я должен всегда искать частные поля?

Это будет против меня, когда будет проведено тестирование?

Это считается чистым/нечистым кодом?

1
de
Здесь я понятия не имею, что MyFoo не определен в этом классе, а скорее в базовом классе. - Это верно с унаследованным методом или свойством any .
добавлено автор sgwill, источник
@Snowman: Если вы слишком слабы, чтобы дать себе собственный закон, тогда тиран возложит на вас свое ярмо и скажет: «Повинуйтесь! Сцепите зубы и повинуйтесь!» И все добро и зло утонут в послушании ему.
добавлено автор CodeCharming, источник
«В нашем случае большую часть времени эти свойства исходят от инъекции зависимостей и доступны в конструкторе обоих классов» - кажется, у вас есть особый случай защищенных свойств, и ваш пример не отражает этого. Голосование закрывается как «слишком широкое» или «неясное».
добавлено автор Peter LeFanu Lumsdaine, источник
Нет ничего хорошего или зла. Есть только власть, и те, кто слишком слаб, чтобы владеть ею.
добавлено автор user22815, источник
.NET CLR содержит более 5000 защищенных свойств, поэтому они, вероятно, не являются злыми. Защита служит для предоставления свойства только производным классам. В примере из CLR проверьте InnerList (и прочитайте документацию, чтобы увидеть предупреждение о том, что Microsoft предоставляет информацию о том, почему это описано таким образом).
добавлено автор John Wu, источник
хмм. возможно, это поможет, если вы добавите пример 2 privates. Я думаю, что вы не получите такое же поведение при кастинге
добавлено автор Ewan, источник
Вы не говорите нам, чего хотите, и почему вы считаете, что защита на вашем пути.
добавлено автор john, источник

3 ответы

Я не думаю, что дублирование свойства в подклассе (и его конструкторе) на самом деле является лучшей альтернативой. Для фактических свойств чтения/записи, которые не могут даже дать такую ​​же функциональность, а для введенных только для чтения свойств, как в вашем случае (возможно, какой-то сервис), это не имеет большого значения, где это определено. Кроме того, ваша IDE может легко вам это показать.

В принципе, способ взглянуть на это заключается в следующем:

  • Защищенные поля являются частью API класса для подкласса, как и методы.
  • Защищенные поля, которые фактически содержат изменяемые данные, могут определенно привести к тому, что код трудно понять, но поэтому могут содержать защищенные методы, когда они переопределяются в подклассах, но вызывается в суперклассе.
  • Проблема здесь не в защищенных полях или методах, проблема заключается в подклассе. Его следует использовать осторожно и экономно.
  • Эмпирическое правило, которое я только что сделал на месте: либо суперкласс должен быть очень маленьким и простым, либо подклассом. И глубокие иерархии наследования плохие.
22
добавлено

вам нужно либо знать, либо проверять вручную, где определен MyFoo

Но как это специфично для защищенных свойств ? То же самое верно для методов и действительно любой публичный член. Одной из основных причин наследования является отсутствие необходимости повторять одно и то же для каждого конкретного типа. Таким образом, вы можете иметь общий базовый тип, который содержит определения базового поведения и базового хранилища.

Защищенное свойство или область просто сообщает вам, что это внутренняя деталь реализации, которая вероятна должна быть релевантна для подклассов. В некотором роде, это фактически говорит вам больше, чем полностью несвязанные частные свойства на каждом уровне.

И компилятор уже знает, где он определен и как его доступно. И хорошие редакторы расскажут вам, что во время разработки, поэтому нет необходимости «проверять вручную». Кроме того, при наследовании типа я бы ожидал, что вам будет комфортно его интерфейс, поэтому вы знаете , что есть защищенные члены, которые вы можете использовать.

В нашем случае эти свойства исходят от инъекции зависимостей

Это может быть только мое мнение, но я всегда использовал бы readonly поля для зависимостей, а не для свойств.

Так что очень просто просто сопоставить их с частными свойствами из этого конструктора

Конечно, у вас может быть личное поле на каждом уровне иерархии типов. Но это также дублирует использование памяти, необходимое для отслеживания этих данных. И если вы на мгновение игнорируете тот факт, что это неизменные зависимости, введенные в конструктор, базовый класс, который не может изменить , значение для его подклассов также может привести к проблемам.

Являются ли защищенные свойства просто вредной привычкой, и должен ли я всегда использовать частные поля?

Здесь есть два вопроса: Свойство против поля и protected vs private . Чтобы ответить на последнее: используйте то, что имеет смысл в смысле инкапсуляции. Если ваш базовый тип имеет фактические внутренние API, которые могут использовать подклассы, они должны быть защищены. Но вы не должны просто делать зависимую защиту на всякий случай .

12
добавлено
Очень согласен. Что происходит, когда частные члены в двух классах имеют (слегка) другое имя? Теперь вы должны посмотреть в 3 или 4 местах, чтобы убедиться, что они относятся к одной и той же вещи.
добавлено автор Anne Aunyme, источник

Являются ли защищенные свойства злыми?

Нет. Защищенные свойства smelly , но не evil . То есть, они должны заставить вас подумать: «Я правильно моделирую это?» Один считает, что свойство является частью общей площади поверхности модели, а поле является частным элементом реализации модели. Поскольку «защищенный» просто означает «частную деталь реализации этой иерархии», можно ожидать, что защищенные поля, а не защищенные свойства.

Тем не менее, защищенные свойства не являются неправильными ; они просто признак того, что, возможно, вам нужно подумать о своем дизайне немного сложнее.

Здесь я не знаю, что MyFoo не определен в этом классе, а скорее в базовом классе.

Конечно, вы это знаете. Вы можете прочитать исходный код класса и ясно видеть, что такого свойства нет. И вы можете «перейти к определению» и перейти к исходному коду для свойства.

Проблема/дебаты состоят в том, что вам нужно либо знать, либо проверять вручную, где определен MyFoo. </Р>

Нет, нет. Почему, по-вашему, вы должны знать, где это определено?

И вам лучше использовать 2 частных поля, один в базовом классе, в дочернем классе.

Нет, я не согласен с этим. Возможно, вам лучше использовать защищенное поле в базовом классе.

Являются ли защищенные свойства просто вредной привычкой, и должен ли я всегда использовать частные поля?

Если вы обнаружите, что пишете много защищенных свойств, я бы спросил, действительно ли они лучше моделируются как защищенные поля. Помните, что свойство должно моделировать свойство моделируемой вещи . Если вы пишете класс Car , тогда его свойства должны быть свойствами автомобиля . Каковы свойства автомобиля и также детали реализации иерархии автомобилей ? Я не могу думать ни о чем, что есть обо всех этих вещах, и поэтому, возможно, не должно быть защищенных свойств.

6
добавлено
«Так как« защищенный »просто означает« частную деталь реализации этой иерархии », один из ожидаемых защищенных полей, а не защищенных свойств». не уверен, что я могу следовать. Конечно, если у меня есть базовый класс и все реализации под контролем, то защищенное свойство бессмысленно. Но если я предоставляю базовый класс, который может быть реализован третьими сторонами, использование свойств вместо полей упрощает изменение реализации в будущем - по той же причине мы используем публичные свойства вместо полей. Почему это будет запах кода?
добавлено автор Kyle Hodgson, источник
@Voo: Я вижу вашу мысль. Здесь есть три вещи: (1) предоставить деталь реализации иерархии классов, (2) сохранить детали этой вещи как самой абстракции и (3) сделать свойства только того, что логически свойства . Все проектные решения включают в себя компромисс между несовместимыми целями; моя точка зрения заключается в том, что если вы находитесь в такой ситуации, вы уделяете немного времени и сил, чтобы убедиться, что дизайн действительно лучший компромисс.
добавлено автор CodeCharming, источник