Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2008.10.26;
Скачать: [xml.tar.bz2];

Вниз

переопределение vs. сокрытие   Найти похожие ветки 

 
tubik ©   (2008-09-16 22:17) [0]

Доброго времени суток. Собственно, вопрос больше относиться к теории. Но хотелось бы разобраться в следующем (следующий фрагмент взят из хэлпа Delphi 7):

If a method declaration specifies the same method identifier and parameter signature as an inherited method, but doesn"t include override, the new declaration merely hides the inherited one without overriding it. Both methods exist in the descendant class, where the method name is statically bound. For example,

type
 T1 = class(TObject)
   procedure Act; virtual;
 end;
 T2 = class(T1)
   procedure Act;  // Act is redeclared, but not overridden
 end;
var
 SomeObject: T1;
begin
 SomeObject := T2.Create;
 SomeObject.Act;  // calls T1.Act
end;

Вопрос заключается в следующем - кто кого в этом примере прячет (hides)? Возможно, пример кода не сильно удачный для того что бы подтвердить слова - "the new declaration merely hides the inherited one without overriding it". Помогите пожалуйста уяснить данный момент. Буду очень благодарен за пример кода демонстрирующий данный нюанс - оverriding vs hiding


 
Медвежонок Пятачок ©   (2008-09-16 22:19) [1]

T2.Act хайдс T1.Act


 
tubik ©   (2008-09-16 22:54) [2]

Оригинальный ответ... Возможно не совсем корректно задал вопрос. То что T2.Act хайдс T1.Act я понимаю (об этом говорится в фрагменте из хелпа). Просто в приведенном примере кода из хелпа - SomeObject.Act; - дейсвтительно вызывается T1.Act. Так при каких обстоятельствах T2.Act будет скрывать T1.Act? Приведите пример кода пожалуйста.


 
palva ©   (2008-09-16 22:57) [3]

Скрывает, значит функция остается, и из объекта T2 можно обратиться как к T1.Act, так и к T1.Act. Если же override, то поднявшись от объекта T2 к родителю мы обнаружим, что функция Act в нем заменена, а старой функции уже не существует.


 
palva ©   (2008-09-16 23:03) [4]


> Так при каких обстоятельствах T2.Act будет скрывать T1.Act?

Будет скрывать, если мы напишем
SomeObject: T2;
Но даже в этом случае можно вызвать родительский метод
T1(SomeObject).Act;


 
palva ©   (2008-09-16 23:11) [5]

Что-то я в недоумении. Программа
{$APPTYPE CONSOLE}
type
T1 = class(TObject)
  procedure Act; virtual;
end;
T2 = class(T1)
  procedure Act;  // Act is redeclared, but not overridden
end;
procedure T1.Act; begin writeln("T1") end;
procedure T2.Act; begin writeln("T2") end;
var
SomeObject: T2;
begin
SomeObject := T2.Create;
(SomeObject As T1).Act;  // T2
end.

печатает T2, хотя, казалось бы, должна печатать T1
Компилятор D7, предупреждение при компиляции выдается...
Как много нам открытий чудных...


 
Медвежонок Пятачок ©   (2008-09-16 23:12) [6]

Просто в приведенном примере кода из хелпа - SomeObject.Act; - дейсвтительно вызывается T1.Act. Так при каких обстоятельствах T2.Act будет скрывать T1.Act? Приведите пример кода пожалуйста.

t2.act статическая
t1.act виртуальная.

кроме того, они еще и одноименные.

вызов статического метода зависит от типа переменной.
вызов виртуального зависит от типа объекта, на который указывает переменная.

плюс еще в этом примере разорвана цепочка так как метод не имеет директивы override.

Чего спрашивал-то? По-русски только.


 
Медвежонок Пятачок ©   (2008-09-16 23:16) [7]

печатает T2, хотя, казалось бы, должна печатать T1

С чего бы вдруг.
переменная типа T2. Метод статический. Вызывается сразу T2.Act и больше ничего не вызывается


 
tubik ©   (2008-09-16 23:27) [8]


> печатает T2, хотя, казалось бы, должна печатать T1
> Компилятор D7, предупреждение при компиляции выдается...
>
> Как много нам открытий чудных...

В таком варианте добился как раз того поведения, что ты хотел/хотела
var
 SomeObject: T2;
begin
 SomeObject := T2.Create;
 T1(SomeObject).Act;// вызывается Т1
end;


 
tubik ©   (2008-09-16 23:33) [9]

>Чего спрашивал-то? По-русски только.
Спасибо... разобрался... тему можно считать закрытой... всем спасибо за помощь...


 
int64   (2008-09-17 00:04) [10]

palva ©   (16.09.08 23:11) [5]

Мистика
В 2007

(SomeObject As T1).Act;  // T2
T1(SomeObject).Act;       // T1


При
{$APPTYPE GUI}  

(SomeObject As T1).Act;  // T1
T1(SomeObject).Act;       // T1


 
tubik ©   (2008-09-17 00:15) [11]


> Мистика
> В 2007

А вот это мне уже начинает нравиться...)))


 
tubik ©   (2008-09-17 00:23) [12]

Пишу на Делфи совсем немного - только 4 месяца... посему не совсем знаю как устроен реализованы механизмы приведения типов - typecast и checked typecast.. очевидно что именно в этом вся загадка - почему при одинаковых действиях - приведение типов - идут совершенно разные результаты?

(SomeObject As T1).Act;  // T2
T1(SomeObject).Act;       // T1


 
Германн ©   (2008-09-17 00:38) [13]


> tubik ©   (17.09.08 00:23) [12]
>
> Пишу на Делфи совсем немного - только 4 месяца... посему
> не совсем знаю как устроен реализованы механизмы приведения
> типов - typecast и checked typecast..

Главную твою ошибку видно в в первых 5 словах этого поста.


 
tubik ©   (2008-09-17 01:54) [14]


> Главную твою ошибку видно в в первых 5 словах этого поста.

фу как это некрасиво


 
Германн ©   (2008-09-17 02:07) [15]


> tubik ©   (17.09.08 01:54) [14]
>
>
> > Главную твою ошибку видно в в первых 5 словах этого поста.
>
>
> фу как это некрасиво
>

Что некрасиво?


 
Джо ©   (2008-09-17 03:59) [16]


> Буду очень благодарен за пример кода демонстрирующий данный
> нюанс - оverriding vs hiding


unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

type
 TForm1 = class(TForm)
   Button1: TButton;
   procedure FormCreate(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

 T1 = class(TObject)
   procedure Act; virtual;
 end;

 T2 = class(T1)
   procedure Act;  // Act is redeclared, but not overridden
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
 SomeObject: T1;
begin
 SomeObject := T2.Create;
 try
   SomeObject.Act;  // calls T1.Act
 finally
   SomeObject.Free
 end;
end;
{ T1 }

procedure T1.Act;
begin
 ShowMessage ("T1.Act");
end;

{ T2 }

procedure T2.Act;
begin
 ShowMessage ("T2.Act");
end;

end.


 
Джо ©   (2008-09-17 04:04) [17]

Ах, да, теперь исправь на

 T2 = class(T1)
   procedure Act;  override;
 end;

И еще раз запусти.


 
palva ©   (2008-09-17 09:25) [18]


Медвежонок Пятачок ©   (16.09.08 23:16) [7]
> С чего бы вдруг.
> переменная типа T2.

А с того, что переменную типа T2 я рассматриваю как переменную типа T1,
(SomeObject As T1).Act;
а у T1 имеется своя процедура Act, которая хоть и виртуальная, но не переопределена, и должна выполняться именно она.


 
Поросенок Винни-Пух ©   (2008-09-17 09:31) [19]

Ну видимо
(SomeObject As T1).Act;
это все равно тип T2


 
tubik ©   (2008-09-17 11:46) [20]


> Медвежонок Пятачок ©   (16.09.08 23:16) [7]
> > С чего бы вдруг.
> > переменная типа T2.
>
> А с того, что переменную типа T2 я рассматриваю как переменную
> типа T1,
> (SomeObject As T1).Act;

palva совершенно справедливо возмущается... он выполнил повыщающее приведение типа, а поскольку мы не переопределили Act в классе Т2, то должна вызываться Act из Т1... правда почему то при проверяемом приведении типа это не происходит...


 
Поросенок Винни-Пух ©   (2008-09-17 11:52) [21]

Да я что, против что ли?

Только вот :
SomeObject := T2.Create;
Writeln((SomeObject As T1).ClassName);
ReadLn;


 
tubik ©   (2008-09-17 12:25) [22]

мне кажется ты путаешь грешное с правидным... дело в том что ClassName это ф-ция класса...

class function ClassName: ShortString;

обращение к ф-циям класса идет через class reference.. а поскольку у нас действительно под ссылкой на базовый класс хранился обьект производного класса, то совершенно логично что после такого вызова Writeln((SomeObject As T1).ClassName); на экране выведется Т2...


 
Поросенок Винни-Пух ©   (2008-09-17 12:33) [23]

не вижу криминала.
ClassName виртуальный, вызыватся для типа, на который указывает переменная, а не для типа переменной.
Значит после приведения в скобках остается T2

Для него же вызывается его статический act


 
tubik ©   (2008-09-17 15:34) [24]

действительно, криминала нет... что то я совсем запутался... просто до того как программировать на Делфи, программировал на С++... если не ошибаюсь, то в С++ статические ф-ции - ф-ции класса - не могут быть виртуальными... вот только что прочитал что в Делфи могут... мой моск этого не вынесет...


 
tubik ©   (2008-09-17 15:37) [25]

я так понимаю, это связано с тем что класс в делфи - это тоже сущность - и представлена она метаклассом, как в Джава...


 
Поросенок Винни-Пух ©   (2008-09-17 15:40) [26]

в си и в д статическими называются немного совсем разные вещи.

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


 
tubik ©   (2008-09-17 15:49) [27]

to Поросенок Винни-Пух
так я понимаю что в С++ и Д под словом статический понимаются разные вещи - "С++ статические ф-ции - ф-ции класса" - тоесть те для которых не нужен экземпляр... так вот в С++ классовые ф-ции не могут быть виртуальными



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2008.10.26;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.006 c
2-1221758923
MZG
2008-09-18 21:28
2008.10.26
Как подсчитать в цикле?


2-1221676471
Евгений Р.
2008-09-17 22:34
2008.10.26
Активная форма MDI приложения


2-1221722320
kate158
2008-09-18 11:18
2008.10.26
сложный sql запрос!!!


15-1220271337
zorik
2008-09-01 16:15
2008.10.26
Построение поверхности за границами изолиний


2-1221620684
Татьяна
2008-09-17 07:04
2008.10.26
Отчеты в Word





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский