Подумайте, что могло бы произойти, если бы все было наоборот.Давайте представим пользовательский класс со значением _id
._id
из 0 - это специальные значения, которые представляют «гостевую» учетную запись (игнорируйте проблемы, связанные с «специальными значениями», во-первых, это не всегда плохая идея, а во-вторых, это только пример)._id
также нельзя изменить после конструирования (что имеет смысл, если его можно было изменить, и он больше не является идентификатором).
public class User
{
private readonly int _id;
public User(int id)
{
_id = id;
}
public int ID
{
get { return _id; }
}
public bool IsGuest
{
get { return _id == 0; }
}
}
Теперь рассмотрим класс Admin, который является подклассом из этого.Одним из правил класса Admin является то, что гость никогда не может быть администратором.Этот инвариант должен применяться во всех точках, которые может изменить статус гостя, который в данном случае находится только в конструкторе:
public class Admin : User
{
public Admin(int id)
:base(id)
{
if(IsGuest)
throw new SecurityException("Guest users cannot be admins.");
}
}
Если Admin
был создан до User
, тогда он всегда будет выдавать это исключение, так как тест всегда сравнивал бы 0 с 0. Если бы у нас было другое специальное значение для гостей, то это было бы еще хуже, и мы никогда не бросили бы исключение, даже когда это было бы необходимо, и учли бы проблему безопасности.
Помните также, что человеку, пишущему класс Admin
, не нужно знать, как работает User
, помимо того, что задокументировано относительно его открытого и защищенного интерфейса.Они могли бы уловить проблему, указанную выше, добавив свой собственный тест для определения того, равен ли id
ноль или нет, но кроме того, что это является ненужным дублированием кода, нет причин, по которым они должны знать, как работает проверка IsGuest
, и этобыть намного более сложным, чем это выше, и, возможно, возможно, запатентованным, запутанным и недокументированным.
В целом, вся концепция «построения администратора» не имеет смысла без концепции «создания пользователя» как чего-то, что произошло в первую очередь, мы не можем сделать более специализированный тип X без созданияX в качестве предпосылки.