Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Операции с классами [D7, XP]


Страницы:   1 2

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".


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо