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

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.49 MB
Время: 0.036 c
14-1121060843
Antonn
2005-07-11 09:47
2005.07.31
Аналог ХР ного msconfig.exe в Win2K


1-1121165114
Piter
2005-07-12 14:45
2005.07.31
Эмуляция нажатия мышкой


1-1121076219
kyn66
2005-07-11 14:03
2005.07.31
Сравнить два набора данных


14-1120716122
vajo
2005-07-07 10:02
2005.07.31
Есть адрес сетевой карты, нужен ее IP


4-1117784323
al_mt
2005-06-03 11:38
2005.07.31
Проблемы с PrintScreen





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский