Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.07.31;
Скачать: CL | DM;

Вниз

Вопрос по наследованию   Найти похожие ветки 

 
753   (2005-07-14 12:39) [0]

Есть описание (пример взят из книги):
type
 T1stObj = class
   i: Extended;
   procedure SetData(AValue: Extended)
 end;

 T2nd0bj = class(T1stObj)
   i: Integer;
   procedure SetData(AValue: Integer)
 end;

procedure T1stObj.SetData;
begin
 i := 1.0
end;

procedure T2nd0bj.SetData;
begin
 i := 1;
 inherited SetData(0.99) //?
end;
Вопрос такой: разве "inherited SetData(0.99)" не вызовет ошибки? Ведь в T2ndObj перекрыто поле i и оно имеет другой тип данных (Integer вместо Extended), поэтому и метод SetData T1stObj нельзя вызывать в потомке. Или я ошибаюсь? Или нет?


 
Юрий Зотов ©   (2005-07-14 12:55) [1]

> в T2ndObj перекрыто поле i

Поля не перекрываются, они добавляются. В классе T2ndObj два поля i - целое (введено в нем самом) и вещественное (унаследовано). Его "родной" метод SetData устанавливает первое, а унаследованный - второе.


 
Fay ©   (2005-07-14 12:56) [2]

2 753   (14.07.05 12:39)
1) Проверить слабо?
2) Читал мельком, но выглядит вполне пристойно.


 
Reindeer Moss Eater ©   (2005-07-14 12:57) [3]

наследуемый SetData принимает параметром Extended;
Ему и передают литерал 0.99.

Какие проблемы?


 
753   (2005-07-14 13:01) [4]

Дальше по тексту:
В этом примере разные методы с именем SetData присваивают значения разным полям с именем i. Перекрытое (одноименное) поле предка недоступно в потомке; поэтому, конечно, два одноименных поля с именем i приведены только для примера.


 
begin...end ©   (2005-07-14 13:07) [5]

> 753   (14.07.05 13:01) [4]
> Перекрытое (одноименное) поле предка недоступно в потомке

Доступно.


 
Юрий Зотов ©   (2005-07-14 13:20) [6]

> 753   (14.07.05 13:01) [4]

> Перекрытое (одноименное) поле предка недоступно в потомке;

Одноименное поле предка в потомке действительно напрямую недоступно, но не по причине его перекрытия. Тут налицо некая путаница в трактовке терминологии ООП.

Перекрываются (override) виртуальные (и динамические) методы. Статические же элементы класса (поля, свойства и статические методы) перекрыть невозможно. Даже если в потомке ввести такой же элемент с тем же именем, то он не перекроет (в смысле ООП) а, согласно общим правилам видимости, просто закроет одноименный элемент предка. Вот аналогичный пример без всякого ООП:

var
 MyVar: integer; // Глобальная переменная

procedure MyProc;
var
 MyVar: integer; // Локальная переменная
begin
 ... // Здесь глобальная переменная MyVar недоступна, потому
 ... // что ее закрыла одноименная локальная переменная
end;

В ряде случаев обратиться к закрытому элементу предка все же можно - через директиву inherited.


 
753   (2005-07-14 13:32) [7]

Большое спасибо всем, особенно Юрию Зотову.
Подводя итог, строчка "inherited SetData(0.99)" обращается к закрытому (недоступному напрямую) методу предка, который устанаавливает значение поля i: Extended в предке.


 
begin...end ©   (2005-07-14 13:33) [8]

> Юрий Зотов ©   (14.07.05 13:20) [6]

> В ряде случаев обратиться к закрытому элементу предка
> все же можно - через директиву inherited.

Поскольку в данном случае речь идёт о полях, то, насколько я понимаю, inherited тут не пройдёт.

> 753   (14.07.05 12:39)

type
 TAncestor = class
   I: Integer;
 end;

 TDescendant = class(TAncestor)
   I: Integer;
 end;

var
 D: TDescendant;
begin
 D := TDescendant.Create;
 // Запись в поле TAncestor.I
 TAncestor(D).I := 1;
 // Запись в поле TDescendant.I
 D.I := 2;
 ShowMessageFmt("%d %d", [TAncestor(D).I, D.I])
end.


 
inherited   (2005-07-14 13:41) [9]

может объяснит кто, почему это не работает?


unit Unit1;
interface
uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs;
type
 TForm1 = class(TForm)
   procedure FormCreate(Sender: TObject);
  end;
    T1stObj = class
    i: extended;
    public
    procedure SetData(AValue: Extended);
     end;
      T2nd0bj = class(T1stObj)
  i: Integer;
  public
  procedure SetData(AValue: Integer);
end;
var
 Form1: TForm1;
 obj: T2nd0bj;
implementation
{$R *.dfm}
procedure T1stObj.SetData;
begin
i := 1.0;
end;
procedure T2nd0bj.SetData;
begin
 i := 1;
inherited SetData(0.99); //?
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
obj.SetData(0);
end;
end.


 
Юрий Зотов ©   (2005-07-14 13:46) [10]

> 753   (14.07.05 13:32) [7]
Точно так.

> begin...end ©   (14.07.05 13:33) [8]
Точно так.  

> 753   (14.07.05 13:32) [7]
Обратите внимание на [8]. Здесь доступ к полю предка осуществляется другим способом - не через inherited, а прямым приведением класса (для полей inherited не прокатывает). То есть, прямым указанием компилятору, какое именно поле он должен в данном месте использовать при генерации машинного кода.

В случае inherited SetData мы тоже напрямую указали компилятору, что в данном месте он должен сгенерить вызов метода предка, а не потомка. Для методов inherited работает.


 
Skyle ©   (2005-07-14 13:48) [11]


> begin
> obj.SetData(0);
> end;


А может obj ещё инициализировать надо? Объект там создать, конструктор вызвать....


 
inherited   (2005-07-14 13:59) [12]

Skyle ©   (14.07.05 13:48) [11]

ну попробуйте поставьте create - ничего не меняется (((


 
begin...end ©   (2005-07-14 14:02) [13]

> inherited   (14.07.05 13:59) [12]

А что должно быть? Оба поля будут равны единице. Всё правильно.


 
Alexander Panov ©   (2005-07-14 14:03) [14]

inherited   (14.07.05 13:59) [12]
ну попробуйте поставьте create - ничего не меняется (((


А вот покажи, как не меняется.


 
inherited   (2005-07-14 14:06) [15]

да я не про значение i, я про EAccessViolation...


 
Alexander Panov ©   (2005-07-14 14:07) [16]

inherited   (14.07.05 14:06) [15]
да я не про значение i, я про EAccessViolation...


Тогда в книжный магазин и изучать основы ООП.


 
begin...end ©   (2005-07-14 14:08) [17]

> inherited   (14.07.05 14:06) [15]

Конструктор здесь нужно вызвать так: obj := T2nd0bj.Create.


 
evvcom ©   (2005-07-14 14:13) [18]


> ... // Здесь глобальная переменная MyVar недоступна, потому
>  ... // что ее закрыла одноименная локальная переменная

Через имя модуля будет доступна. (Это не камень в огород Юрия, а уточнение для вопрошающих) :)



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

Текущий архив: 2005.07.31;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.042 c
14-1121080212
vers
2005-07-11 15:10
2005.07.31
Прикол Delphi 2005


6-1113996587
MegaVolt
2005-04-20 15:29
2005.07.31
Как определить когда появляется запись в ARP таблице?


6-1113840746
_Seldon_
2005-04-18 20:12
2005.07.31
Контекстное меню дла файла в сети


3-1118911425
evg00
2005-06-16 12:43
2005.07.31
синтаксис запроса


3-1119553881
chi
2005-06-23 23:11
2005.07.31
Что понимается под свойством Handle для таблицы Paradox?