Наследование.NET: подавите свойство от базового класса

Рассмотрите Сотрудника, менеджера и классы Помощника:

public class Emp
{
    public string Name { get; set; }
    public Manager Manager { get; set; }
    public Assistant Assistant { get; set; }
}

public class Manager : Emp
{ 
}

public class Assistant : Emp
{
}

Цель состоит в том, чтобы НЕ РАЗРЕШИТЬ части кода получать доступ к свойству как это:

var foo = new Manager();
var elmo = new Emp();
elmo.Manager = foo;
elmo.Manager.Manager = new Manager(); 
//how to disallow access to Manager.Manager ?

Поскольку Manager наследовался Emp, это имеет a .Manager и .Assistant свойство.

Вопрос

Есть ли любые модификаторы в реализации наследования.NET для удаления .Manager и .Assistant свойства?

Обновление

Спасибо за Ваши большие ответы, всех. Я надеялся, что упрощение и приспособление Emp/Mgr покажут через в этом вопросе. Ясно, что наследование, в этом примере, должно быть взято к другой общности (что-то как Person, где классы совместно использовали бы имена, даты рождения, и т.д.), Ваш вход очень ценится!

8
задан p.campbell 20 January 2010 в 05:34
поделиться

6 ответов

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

9
ответ дан 5 December 2019 в 10:03
поделиться

Нет - потому что он сломал Принцип субситирования Liskov . По сути, вы можете добавить вещи, но вы не можете забрать их.

Вы можете потенциально переопределить свойство, чтобы выбросить исключение при исполнении времени, но вы не можете сделать это во время компиляции.

Как правило, если вы хотите запретить эту вещь, вы должны рассмотреть состав, а не наследство, так как у вас нет подлинных отношений на наследстве.

5
ответ дан 5 December 2019 в 10:03
поделиться

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

0
ответ дан 5 December 2019 в 10:03
поделиться
-

Нет, не существует.

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

(elmo.Manager as Employee).Manager = new Manager();

Однако, вы можете записать

public class ManagerEmployee : Emp {     
    public new ManagerEmployee Manager { 
        get { return base.Manager; }
    }
}

Заметьте, что это не предотвратит кастинг.

2
ответ дан 5 December 2019 в 10:03
поделиться

Как и большинство вещей, это зависит. Учитывая следующие классы:

public class foo
{
    public string Test { get { return "foo"; } } 
}

public class bar : foo
{
    public new string Test { get { return "bar"; } }
}

и следующий код:

        bar a = new bar();
        // returns bar
        literalTest1.Text = a.Test;

        foo b = new foo();
        // returns "foo"
        literalTest2.Text = b.Test;

        foo c = new bar();
        // returns "foo"
        literalTest3.Text = c.Test;

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

вместо этого исправьте класс вашего предка.

1
ответ дан 5 December 2019 в 10:03
поделиться

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

0
ответ дан 5 December 2019 в 10:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: