Изменение модификатора доступа метода в производном типе не имеет смысла, поэтому оно не разрешено:
Случай 1: переопределить с более ограничительным доступом
Этот случай явно не разрешен из-зак следующей ситуации:
class Base
{
public virtual void A() {}
}
class Derived: Base
{
protected override void A()
}
Теперь мы можем сказать:
List<Base> list;
list.Add(new Derived());
list[0].A() //Runtime access exception
Случай 2: Переопределение с менее модифицированным модификатором доступа
Какой смысл?Скройте метод, и все готово.Очевидно, что если кто-то вызывает через базовый тип, у него не будет доступа к новому методу, определенному в производном типе, но это согласуется с тем, как этого хотел автор базового типа, поэтому у вас нет «права» изменить это.Если вам нужна специфика вызова производного класса из производного класса, то в этом случае метод new
отлично работает.
РЕДАКТИРОВАТЬ: Расширяющий регистр 2
В случае 2 я пытаюсь сказать, что у вас уже есть средства для изменения доступности любого метода (виртуального или нет), если вы хотите изменить доступность.
Рассмотрим следующий код:
public class Base
{
protected virtual string WhoAmI()
{
return "Base";
}
}
public class Derived : Base
{
public new virtual string WhoAmI()
{
return "Derived";
}
}
public class AnotherDerived : Derived
{
public override string WhoAmI()
{
return "AnotherDerived";
}
}
С помощью ключевого слова new
вы фактически создали новый виртуальный метод для вашего класса Derived
с тем же именем и подписью.Обратите внимание, что РАЗРЕШЕНО объявлять метод new
virtual
, поэтому любой класс, производный от Derived
, сможет переопределить его.
Недопустимо, чтобы кто-то сделал следующее:
Base newBaseObject = new Derived();
newBaseObject.WhoAmI() //WhoAmI is not accessible.
Но этот факт не имеет ничего общего с возможностью переопределить WhoAmI()
или нет.В любом случае, такая ситуация никогда не может быть, потому что Base
не объявляет public
WhoAmI()
.
Так что в теоретическом C #, где Derived.WhoAmI()
может переопределить Base.WhoAmI()
, практических преимуществ в этом неттак как вы все равно никогда не сможете вызывать виртуальный метод из базового класса, поэтому опция new
уже отвечает вашим требованиям.
Надеюсь, это прояснит ситуацию.