Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > .NET для новичков > Переопределение объектов


Автор: ЛунныйОборотень 10.6.2013, 19:47
Здравствуйте!

Подскажите пожалуйста такую вещь.

Например, есть класс А и отнаследованный от него класс B.

Что получится, если написать B=new A()?Получится, что B станет фактически A?

Спасибо.

Автор: Экскалупатор 10.6.2013, 20:20
Фактически будет ошибка приведения типов, потому что А не может приводиться к B.

Автор: boevik 10.6.2013, 20:21
Это не пройдет компиляцию.
Можно так:
Код

A a = new B()

В run-time в переменной а находится обэкт B.

Автор: Arantir 10.6.2013, 20:29
Цитата(ЛунныйОборотень @  10.6.2013,  18:47 Найти цитируемый пост)
Что получится, если написать B=new A()?

Так нельзя написать. Потому что A "не знает" о B.
Можно написать 
Код

A b = new B();

Почитайте о ключевом слове virtual. Оно как раз для таких случаев. Если есть виртуальный метод из A, и такой же переопределенный в В, то в вышеописанном случае будет использоваться именно переопределенный метод, не смотря на то, что тип переменной — А. Не виртуальные же методы будут взяты как раз из класса А, по типу переменной, а не по объекту.

Но, вообще, это частный случай. Подобный код становится более логичным и полезным, когда A — это абстрактный класс либо интерфейс. Тогда это код просто будет означать, что В должен наследовать/реализовывать А. Это полезно, если класс В формируется динамически или не является частю программы (если это какой-то фреймворк и В должен реализовать пользователь).

Автор: ЛунныйОборотень 17.6.2013, 21:38
с virtual я знаком, но видимо, не правильно выразил вопрос.
Например, можно ли написать и есть ли смысл в выражении 
Код

List list=new ArrayList();

Получается, что это объект реализующий фактически ArrayList?
Спасибо.

Автор: Arantir 17.6.2013, 21:58
Цитата(ЛунныйОборотень @  17.6.2013,  20:38 Найти цитируемый пост)
Например, можно ли написать и есть ли смысл в выражении 

Вообще-то, это код скорее из Java, чем из C#.
Но, знаете, на самом деле сути ответа это совершенно не меняет.

Можно записать только так
Код

Parent obj = new Child();
 если Child реализует/наследует Parent. 

В C# нельзя записать
Код

List<int> list = new ArrayList();
потому что класс ArrayList не наследует класс List.
Так можно записать в Java, потому что List - это интерфейс и его реализует класс ArrayList.

Вообще суть этой записи следующая:
Я создаю объект, который имеет все поля и методы List. А как именно они будут работать - зависит от класса в правой части выражения. В данном примере методы работают так, как описано в ArrayList.

А смысл таков:
Я могу заменить ArrayList на что душе угодно, реализующее List, и при этом мне не придется переписывать больше ни одной строки в программе.
Более общий случай из этого - я могу написать программу, которая работает с любым классом, реализующим List.

Добавлено через 3 минуты и 58 секунд
Цитата(ЛунныйОборотень @  17.6.2013,  20:38 Найти цитируемый пост)
Получается, что это объект реализующий фактически ArrayList?

Все наоборот. В вашем примере объект будет являться реализацией List и экземпляром ArrayList. То, что реализует ArrayList - это сам ArrayList, если так можно выразиться, так как это просто класс (не интерфейс и не абстрактный).

Автор: diadiavova 18.6.2013, 11:20
Цитата(ЛунныйОборотень @  17.6.2013,  22:38 Найти цитируемый пост)
Например, можно ли написать и есть ли смысл в выражении 

Если говорить не о конкретно этом выражении, а о выражениях такого типа, то смысл вполне себе может быть. Здесь имеет место неявное приведение типов, а оно иногда имеет последствия. То есть иными словами, один и тот же объект, будучи загруженным в переменные разных типов может вести себя по разному. 
В первую очередь такое поведение имеет место в случаях явной реализации интерфейсов. То есть, в тех ситуациях, когда в одном классе реализуется несколько интерфейсов, может статься, что два интерфейса имеют члены с одинаковыми сигнатурами, в этих случаях такие члены надо реализовывать, явно указывая какой именно интерфейс имеется в виду. Тогда такой метод будет доступен только при приведении типа к данному интерфейсу. В том же бейсике, реализация интерфейсов организована несколько иначе и там вообще не важно как называется метод, реализующий декларацию из интерфейса и вызывая у класса метод с именем, совпадающим с именем метода интерфейса, в принципе нельзя быть уверенным, что это тот самый метод.
В качестве другого примера можно привести затеняющие декларации ( с использованием ключевого слова new, хотя оно в таких ситуациях и необязательно). То есть если в производном классе объявляется член с сигнатурой, совпадающей с сигнатурой члена базового класса, то член базового класса может быть не виден в производном, но при приведении к базовому типу вызываться будет именно он(этим затенение отличается от переопределения).

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)