Глава.6 .Основные.сведения.о.членах.и.типах
base.Dial();
}
protected virtual void EstablishConnection() {
Console.WriteLine("BetterPhone.EstablishConnection");
// Выполнить действия по набору телефонного номера
}
}
}
При попытке скомпилировать свой код разработчики компании
CompanyB
полу-
чают от компилятора C# предупреждение:
warning CS0108: 'CompanyB.BetterPhone.Dial()' hides inherited member
'CompanyA.Phone.Dial()'. Use the new keyword if hiding
was intended.
Смысл в том, что метод
Dial
, определяемый в типе
BetterPhone
, скроет одно-
именный метод в
Phone
. В новой версии метода
Dial
его семантика может стать
совсем иной, нежели та, что определена программистами компании
CompanyА
в ис-
ходной версии метода.
Предупреждение о таких потенциальных семантических несоответствиях —
очень полезная функция компилятора. Компилятор также подсказывает, как
избавиться от этого предупреждения: нужно поставить ключевое слово
new
перед
определением метода
Dial
в классе
BetterPhone
. Вот как выглядит исправленный
класс
BetterPhone
:
namespace CompanyB {
public class BetterPhone : CompanyA.Phone {
// Этот метод Dial никак не связан с одноименным методом класса Phone
public new void Dial() {
Console.WriteLine("BetterPhone.Dial");
EstablishConnection();
base.Dial();
}
protected virtual void EstablishConnection() {
Console.WriteLine("BetterPhone.EstablishConnection");
// Выполнить действия по установлению соединения
}
}
}
Теперь компания
CompanyB
может использовать в своем приложении тип
BetterPhone
следующим образом:
public sealed class Program {
public static void Main() {
CompanyB.BetterPhone phone = new CompanyB.BetterPhone();
phone.Dial();
}
}
207
Компоненты,.полиморфизм.и.версии
При выполнении этого кода выводится следующая информация:
BetterPhone.Dial
BetterPhone.EstablishConnection
Phone.Dial
Результат свидетельствует о том, что код выполняет именно те действия, кото-
рые нужны компании
CompanyB
. При вызове
Dial
вызывается новая версия этого
метода, определенная в типе
BetterPhone
. Она сначала вызывает виртуальный
метод
EstablishConnection
, а затем — исходную версию метода
Dial
из базового
типа
Phone
.
А теперь представим, что несколько компаний решили использовать тип
Phone
,
созданный в компании
CompanyА
. Допустим также, что все они сочли полезным
установление соединения в самом методе
Dial
. Эти отзывы заставили разработчиков
компании
CompanyА
усовершенствовать класс
Phone
:
namespace CompanyA {
public class Phone {
public void Dial() {
Console.WriteLine("Phone.Dial");
EstablishConnection();
// Выполнить действия по набору телефонного номера
}
protected virtual void EstablishConnection() {
Console.WriteLine("Phone.EstablishConnection");
// Выполнить действия по установлению соединения
}
}
}
В результате теперь разработчики компании
CompanyB
при компиляции своего
типа
BetterPhone
(производного от новой версии
Phone
) получают следующее
предупреждение:
warning CS0114: 'BetterPhone.EstablishConnection()' hi
des inherited member
'Phone.EstablishConnection()'. To make the current member override
that implementation, add the override keyword. Otherwise,
add the new keyword
В нем говорится о том, что
'BetterPhone. EstablishConnection()'
скрывает
унаследованный член
'Phone.EstablishConnection()'
, и чтобы текущий член
переопределил реализацию, нужно вставить ключевое слово
override
; в противном
случае нужно вставить ключевое слово
new
.
То есть компилятор предупреждает, что как
Phone
, так и
BetterPhone
предла-
гают метод
EstablishConnection
, семантика которого может отличаться в разных
классах. В этом случае простая перекомпиляция
BetterPhone
больше не может
гарантировать, что новая версия метода будет работать так же, как прежняя, опреде-
ленная в типе
Phone
.
208
Do'stlaringiz bilan baham: |