![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Операции с классами [D7, XP]
Nickolay © (2010-12-08 09:27:00)Здравствуйте!
Кто может объяснить следующую особенность операции as (Obj as TObj)?
В справке говорится, что она возвращает ссылку на объект Obj как на
объект уже класса TObj. Причём Obj должен быть из TObj или быть его потомком.
Короче, as приводит Obj к нужному типу TObj.
Я завожу два класса - предок TA и потомок TB. Переобъявляю в TB поле,
перекрываю статический метод. Затем преобразую тип объекта B из TB к TA.
Но тип не преобразовывается с помощью as! Функциональное преобразование
работает. Если правым операндом поставить переменную-ссылку на класс TA,
то и as работает. А вот если правый операнд - просто тип TA, то не работает!
Что это - ошибка в компиляторе?
type
TAClass = class of TA;
TA = class // объявление класса-предка
public
Val: Integer;
procedure Met;
end;
TB = class(TA) // объявление класса-потомка
public
Val: string; // теперь поле предка скрыто
procedure Met;
end;
procedure TA.Met;
begin
WriteLn('Это TA.Met')
end;
procedure TB.Met;
begin
WriteLn('Это TB.Met')
end;
var
B: TB;
Aref: TAClass;
begin
Aref := TA; // переменная-ссылка на класс-предок
B := TB.Create; // B - экземпляр класса-потомка
B.Val := 'Ноябрь'; // работаем со своим полем
B.Met; // вызываем свой статический метод
TA(B).Val := 18; // работаем с полем предка
TA(B).Met; // вызываем метод предка
(B as Aref).Val := 18;// работаем с полем предка
(B as Aref).Met; // вызываем метод предка
(B as TA).Val := 18; // здесь операция as не работает - ошибка
(B as TA).Met; // здесь операция as не работает - вызов метода потомка
Anatoly Podgoretsky (2010-12-10 15:16:00) [1]> Ega23 (10.12.2010 11:46:37) [37]
Или не заходи совсем.
Ega23 (2010-12-10 11:46:00) [2]1. А почему вы решили, что это "глюк Delphi"?
2. Насчёт QC - заходи под тем ником или e-mail, под которым Delphi регистрировал (или активизировал? Не, регистрировал) у них на сайте.
Nickolay (2010-12-10 10:55:00) [3]
> И. Павел © (09.12.10 08:40) [33]
QC -Embarcadero Quality Central
тикет - сообщение им
http://qc.embarcadero.com/wc/qcmain.aspx?p=10
Ega23 © (09.12.10 14:35) [35]
В QC не забудьте написать...
Я ещё раз извиняюсь. Зашёл по указанному адресу и ничего не понял, в силу, видимо, тупости. Единственно, что похоже на возможность связаться с ними это "connect with us...". Зарегистрировался, например, в Facebook. А там чего только нет - и фотографии, и друзья, и безопасность и т.д., но вот как через них послать своё сообщение в это QC - опять убейте, не пойму. На "стену" им объявление написать что ли?
Просветите тупого человека, пожалуйста!
Ega23 (2010-12-09 14:35:00) [4]В QC не забудьте написать...
Servy (2010-12-09 10:23:00) [5]
> 1) Тогда можете смело обижаться на Страуструпа. Он в в своём
> описании C++ прямо-таки смакует возможность переобъявления
> одноимённых полей классов и доступа к скрытому полю с помощью
> операции ::.
> Что касается меня, то я отнюдь не "за" такие штучки, а тоже
> "против". Но раз они придумали такие механизмы в C++ и Delphi,
> то пусть отвечают за их работоспособность, а не вводят
> в заблуждение.
У меня и так большие претензии к этому изобретателю, так что дополнительная обида за смакование штучек сильно мое мнение о нем не изменит.
По поводу штучек - даже с буквоедской позиции (так как с точки зрения здравого смысла понятно, что такой typecast нафиг не сдался) можно вам возразить:
the inherited Value is hidden by the new one, and can be accessed through a typecast
Доступ к скрытому значению может быть получен с помощью typecast.
as - описывается как "checked typecast", а не просто "typecast", про него в приведенном выше фрагменте не говорилось. Таким образом, можно считать, что as производит typecast, но может как давать, так и не давать доступа к скрытым полям. Если вам нужен именно доступ к скрытым полям - используйте именно typecast.
Впрочем, заниматься буквоедством - занятие весьма унылое, я больше не буду ^_^.
> А в новых версиях Delphi кто-нибудь пробовал?
Пробовал в 2010, та же ерунда.
И. Павел (2010-12-09 08:40:00) [6]> тикет в QC
QC -Embarcadero Quality Central
тикет - сообщение им
http://qc.embarcadero.com/wc/qcmain.aspx?p=10
> Кстати, все свои примеры я прогнал через компилятор Free
> Pascal
А в новых версиях Delphi кто-нибудь пробовал?
Nickolay (2010-12-09 08:25:00) [7]
> Servy © (08.12.10 12:33) [16]
Я извиняюсь. Я на этот Ваш предпоследний пост тоже написал, может Вы не заметили? Меня всё-таки интересует, что значит "тикет в QC". Не подскажете?
Кстати, все свои примеры я прогнал через компилятор Free Pascal в режиме {$Mode Delphi} и всё прошло без всяких "багов". С помощью as получал доступ из потомка к скрытому полю и статическому методу предка во всех случаях.
Ega23 (2010-12-08 15:24:00) [8]
> Пиплы, травы отсыпьте.
Тссс, не спугни такую прелесть.
DiamondShark (2010-12-08 15:18:00) [9]Пиплы, травы отсыпьте.
Nickolay (2010-12-08 15:03:00) [10]
> Palladin © (08.12.10 14:52) [28]
Это всё понятно. По теме чего-нибудь скажете? Если - нет, то - проехали.
Palladin (2010-12-08 14:52:00) [11]Ну понятно. Я тоже могу долбится головой об стену, мотивировав это изучением сопромата.
Nickolay (2010-12-08 14:46:00) [12]
> Palladin © (08.12.10 14:31) [26]
Зачем?
Изучаю язык Дельфи.
Palladin (2010-12-08 14:31:00) [13]
> Nickolay (08.12.10 10:44) [4]
Ты приводишь объект к типу класса, не к другому классу, а к его метатипу, если можно так сказать. Применяешь на уровне времени-исполнения. Зачем?
Nickolay (2010-12-08 13:58:00) [14]
> Медвежонок ХМЛ © (08.12.10 13:51) [24]
> но не указан случай :
> A.Met;
Согласен, это не указал.
A.Met;
опять-таки вызовет метод потомка и опять-таки в силу полиморфизма,
то есть, другими словами, в A сидит ссылка на TB и поэтому вызывается его метод.
Таким образом, повторяю, что мы говорим про одно и то же, но только разными словами.
Медвежонок ХМЛ (2010-12-08 13:51:00) [15]но не указан случай :
A.Met;
когда
A := TB.Create;
Nickolay (2010-12-08 13:47:00) [16]
> Медвежонок ХМЛ © (08.12.10 13:21) [22]
Я говорю про то же, но только другими словами.
type
TAClass = class of TA;
TA = class // объявление класса-предка
procedure Met; virtual;
end;
TB = class(TA) // объявление класса-потомка
procedure Met; override;
end;
procedure TA.Met;
begin
WriteLn('Это TA.Met')
end;
procedure TB.Met;
begin
WriteLn('Это TB.Met')
end;
var
A: TA;
B: TB;
Aref: TAClass;
begin
A := TB.Create; // A - экземпляр всё-таки класса-потомка
TB(A).Met;
(A as TB).Met;
Aref := TA; // переменная-ссылка на класс-предок
B := TB.Create; // B - экземпляр класса-потомка
B.Met;
TA(B).Met;
(B as Aref).Met;
(B as TA).Met;
Во всех этих случаях будет вызываться метод потомка.
Медвежонок ХМЛ (2010-12-08 13:21:00) [17]то для потомка будет вызываться метод потомка.
Ну осталось еще уяснить, что потомок это или не потомок - определяется не типом переменной а типом экземпляра.
Nickolay (2010-12-08 13:12:00) [18]
> Медвежонок ХМЛ © (08.12.10 12:58) [18]
А если метод динамический, то типом объекта, на который содержится ссылка в переменной.
Это естественно! И для этого методы объявляются виртуальными или динамическими, а потом перекрываются, чтобы реализовать принцип полиморфизма. Поэтому если во всех этих примерах метод виртуализировать, а потом перекрывать, то для потомка будет вызываться метод потомка.
Servy (2010-12-08 13:11:00) [19]
> А я никогда не утверждал и не утверждаю, что "надо делать
> так".
> Я просто показываю, что данный "механизм Дельфи", похоже,
> работает не всегда.
Ага, а я вас поблагодарил за интересную демонстрацию особенности. Мне вполне понятно, как работает данный механизм, и в каком случае результат может отличаться от ожидаемого. И эти случаи относятся к варианту, который, как мы с вами согласились, в реальных проектах лучше не использовать.
> Зачем TObject? Я просто поменяю ролями TA и TB
TObject - предок TA, так что большой разницы нет. Главное, что в этом случае as не бесполезен, а значит компилятор его не выбросит.
Nickolay (2010-12-08 13:03:00) [20]
> Servy © (08.12.10 12:33) [16]
1) Давать одинаковые имена полям или методам - плохая идея в целом, так как человек идентифицирует по имени сущность. И если вместо одной сущности Val у объекта окажется две сущности с таким именем, и где-то идет работа с одной, а где-то с другой, а мне бы пришлось потом поддерживать этот код, я бы на того, кто это написал сильно обиделся.
2) Если вы все еще считаете, что это баг - создайте тикет в QC.
1) Тогда можете смело обижаться на Страуструпа. Он в в своём описании C++ прямо-таки смакует возможность переобъявления одноимённых полей классов и доступа к скрытому полю с помощью операции ::.
Что касается меня, то я отнюдь не "за" такие штучки, а тоже "против". Но раз они придумали такие механизмы в C++ и Delphi, то пусть отвечают за их работоспособность, а не вводят в заблуждение.
2) Объясните, пожалуйста, подробнее, что значит "тикет в QC".