Как мне заблокировать новый модификатор? - PullRequest
4 голосов
/ 17 февраля 2012

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

private int _threadHostID = 0;
    public int ThreadHostID
    {
        get
        {
            if (_threadHostID == 0)
            {
                _threadHostID = ThreadQueue.RequestHostID();
            }
            return _threadHostID;
        }
    }

Редактировать: полностью забыл язык: C #.

Edit2: Это не виртуальноили переопределить что-либо еще, поэтому, пожалуйста, не sealed.

Ответы [ 5 ]

9 голосов
/ 17 февраля 2012

Прежде всего: «Переопределение» относится к виртуальному переопределению. Вы говорите о создании сокрытия методов, а не переопределения методов.

У меня есть свойство в базовом классе, которое я не хочу скрывать

Вы можете этого хотеть, но вам придется научиться жить с разочарованием того, что вы не получаете того, чего хотите.

Я не вижу причин, чтобы кто-то это скрывал.

Тогда проблем не будет, не так ли? Если никто не сможет хотеть скрыть это, то они не будут это скрывать. Вы в основном говорите: «У меня есть объект, который ни для кого не имеет значения; как мне удержать кого-то от его кражи?» Ну, если это бесполезно, то никто не захочет его украсть, так зачем вам тратить деньги на сейф, чтобы защитить то, что никто не хочет украсть?

Если у кого-то нет причин скрывать или отменять ваш метод, то никто не будет. Если является причиной для того, чтобы кто-то скрыл или переопределил ваш метод, то кто вы такой, чтобы говорить им не делать этого? Вы предоставляете базовый класс; вы слуга автора производного класса, а не их хозяин .

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

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

8 голосов
/ 17 февраля 2012

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

Если производный класс скрывает его с помощью оператора new, то они открывают для себя проблемы, поскольку любой код, который решит использовать ссылку на базовый класс, не будет касаться производного члена. Таким образом, в основном, весь код, который использует "базовый класс" иерархии типов, все равно будет обходить скрытие всех членов.

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

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

2 голосов
/ 17 февраля 2012

Думаю, тебе не стоит об этом беспокоиться. Если вы не пишете его как виртуальный, тогда вы даете понять, что он не предназначен для переопределения, и фактически вы получите предупреждение, если переопределите его (без модификатора «new»):

Warning: [...] hides inherited member [...].
Use the new keyword if hiding was intended

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

0 голосов
/ 17 февраля 2012

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

0 голосов
/ 17 февраля 2012

Насколько я могу судить, вы, очевидно, не можете сделать это на уровне собственности. Однако, если вы запечатали класс:

public class Base
{
  public int ID { get; set; } 
}

public sealed class Child : Base
{
  /// blah
}

тогда ...

public class Grandchild : Child
{ 
  public int ID { get; set; } 
}

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

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

...