Главная страница
    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.044 c
9-1113321975
Kobik
2005-04-12 20:06
2005.07.31
Физика или шизика для аркады?


1-1120813858
Shlomo
2005-07-08 13:10
2005.07.31
ClientDataSet: проблема с Lookup полем.


1-1121179818
salexn
2005-07-12 18:50
2005.07.31
Встроенная форма из DLL


4-1117945682
QAndrey
2005-06-05 08:28
2005.07.31
Icon в меню


1-1121338649
webpauk
2005-07-14 14:57
2005.07.31
Свойства файла





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