Вложенные классы недооценены?

9

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

Это приводит меня к вопросу: иду ли я по изначально плохому пути по причинам, которые я обнаружу, когда они вернутся, чтобы укусить меня, или вложенные классы могут быть чем-то недооцененным?

Вот два примера, для которых я только что использовал их: https://gist.github.com/3975581 - первый помог мне сохранить вместе тесно сплетенные иерархические вещи, второй позволил мне предоставить доступ к защищенным членам для рабочих ...

Аарон Анодид
источник
Я просто хочу поблагодарить за ответы / идеи - я не знаю, как выбрать ответ, поэтому я оставлю его, пока обдумываю полученный совет и
повторяюсь

Ответы:

6

Я бы не назвал это «редко используемым механизмом проектирования» - по крайней мере, не универсально: хотя есть магазины, в которых некоторые участники могут нахмуриться, используя вложенные классы, это вовсе не неясная функция.

Хотя наличие классов с видимостью сборки и введение лямбда-выражений значительно сократило потребность во вложенных классах * , они остаются допустимым выбором дизайна. Хотя внутренние пространства внутри пространства имен частично перекрываются, функция вложенных классов уникальна, поскольку позволяет полностью скрыть класс внутри другого класса.


* Использование аналогичной функции в Java намного выше, потому что других альтернатив, доступных в C #, в Java нет.

dasblinkenlight
источник
Так хорошо ли спрятать класс целиком в другом классе согласно сути ООП-дизайна?
Maxood
1
@Maxood Хорошо спрятать класс, если ты можешь это скрыть. Пользователь вашего API должен знать как можно меньше о том, как реализован ваш API.
dasblinkenlight
3

Подумайте на минуту, что вы пишете класс внутри другого класса, который никогда не будет использоваться где-либо еще в вашей программе. Потому что, если бы вы использовали его в другом месте, вы бы сделали его обычным публичным классом, как и все остальные.

Так что то, что должно сделать ООП великим (возможность повторного использования), здесь отсутствует. Кроме того, чего вы можете достичь с помощью вложенного класса, чего не можете достичь с помощью обычных методов и закрытых членов родительского класса?

Для полезного программного шаблона, использующего вложенные классы, посмотрите здесь .

Роберт Харви
источник
10
Я никогда не покупал вещь для повторного использования, по крайней мере, не так, как обычно. (1) Вызов в существующий код / ​​классы (о которых вы, кажется, говорите и которые я обычно вижу как определение повторного использования) не имеет абсолютно никакого отношения к ООП, это просто базовая модульность. (2) Полиморфизм подтипов, который является одной из определяющих характеристик ООП, позволяет повторно использовать клиентский код , делая конкретную реализацию неактуальной , то есть он работает точно так же, независимо от того, доступен конкретный класс или нет. Я покупаю это повторное использование, но оно работает и с вложенными классами.
1
Я бы сказал, что есть также изоляция пространства имен, предоставляемая родительским классом - так что, если вы хотите, оба класса A и B могли бы иметь вложенный класс «Params» и доступ к закрытым членам содержащего класса. Не являются ли они обеими причинами иметь внутренние классы, которые используются вне класса?
Аарон Анодид
@AaronAnodide Это должен быть ответ о хорошем способе использования вложенных классов. Это именно то, как / почему я их использую, это помогает организовать код.
Изката
2

am I going down an inherintly bad path

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

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

Что касается примера части тела. Поскольку все вложенные классы являются общедоступными, на самом деле вы мало что делаете, кроме пространства имен. Если эти классы расширяются и включают больше функциональности, вы можете просто обнаружить, что вложенные классы просто загромождают интерфейсы, и вы просматриваете код, чтобы найти что-то конкретное. Я также заметил, что, поскольку у вас есть вложенные классы, вы вынуждены нарушать соглашения об именах и называть свои классы строчными буквами (возможно, это был выбор). Но эти аргументы являются более поверхностными, чем что-либо на самом деле неправильно.

Если, конечно, вам не нужно было реализовать бестелесную руку. Затем создание руки с помощью следующего сбивает с толку, потому что нет тела / туловища / стороны. (Также обратите внимание на запутанный корпус).

arm newArm = new Body.torso.side.arm("");
nickles80
источник
1

Единственное преимущество, которое я могу придумать для вложенных классов, это то, что они могут быть сделаны частными (или защищенными). Я бы сказал, что в этом случае вложенные классы могут помочь вам инкапсулировать функциональность, если класс предназначен для использования внешним классом и только этим классом.

Бок МакДонах
источник
1

По моему опыту, вложенные классы

  • Вернулся, чтобы преследовать меня
  • Были использованы, когда я хотел срезать углы
  • Сделал тестирование кошмаром
  • Оказал негативное влияние на разделение проблем и общий дизайн

Я кратко посмотрел на ваш класс, и сразу же я думаю, что:

  • На это больно смотреть, потому что класс огромный
  • Я не могу проверить "пальцы" без создания всего тела
  • Я не могу иметь несколько реализаций туловища. Не кажется очевидным в контексте "человеческого тела", но в другом сценарии это станет очевидным.

Почему бы не разделить ваш класс на несколько классов и дать им отдельные пространства имен. Например

WindowsGame1.PhysicalModel.UpperBody
WindowsGame1.PhysicalModel.LowerBody
WindowsGame1.PhysicalModel.UpperBody.Arms
CodeART
источник