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

Вниз

Класс и Объект   Найти похожие ветки 

 
capkoh   (2005-03-13 21:47) [0]

Объясните ламеру, чем отличается класс от объекта в Delphi (У меня 7). Имеется в виду следующее: есть такие объявления:

type
   TSomeClass = class (...) end;
   TSomeObject = object (...) end;

var
  SomeClass: TSomeClass;
  SomeObject: TSomeObject;

При этом в SomeClass уже имеются какие-то методы (ClassName, Dispatch...), а в SomeObject нет. Я так полагаю, что class"ы нужны для создания визуальных компонентов, в object"ы для структур данных. Так вот, в чем же Существенная между ними разница?


 
Sergey_Masloff   (2005-03-13 21:55) [1]

Прочел бы ты справку для начала. Потом про существенную поговорим.


 
jack128 ©   (2005-03-13 22:02) [2]

object - устаревшая конструкция. Обозначает примерно тоже, что и class за определенными искючениями и ограничениями(в часности object"ы не имееют единого предка, в отличее от class"ов, переменные данного типа не являются указателями, и тд и тп)


 
begin...end ©   (2005-03-13 22:07) [3]

> capkoh   (13.03.05 21:47)

> Я так полагаю, что class"ы нужны для создания
> визуальных компонентов, в object"ы для структур данных.

Object"ы могут использоваться не только как структуры данных. Они так же, как и классы, могут содержать поля, свойства и методы. Правда, все эти составляющие не могут быть объявлены в разделе published. У object"ов нет конструкторов и деструкторов. Можно объявлять переменную нужного объектного типа и сразу с ней работать, или объявлять переменную-указатель на объектный тип, и выделять для неё память динамически с помощью процедур New и Dispose.

Вот пример описания object"а:

interface
 
 type
   TMyObject = object
   public
     ObjField: String;
     procedure ShowObjField;
     property ObjProperty: String read ObjField write ObjField;
   end;

...

implementation

procedure TMyObject.ShowObjField;
begin
 ShowMessage(ObjField)
end


А работать с ним можно так:

var
 MyObject: ^TMyObject;
begin
 New(MyObject);
 MyObject.ObjProperty := "text";
 MyObject.ShowObjField;
 Dispose(MyObject)
end


или так:

var
 MyObject: TMyObject;
begin
 MyObject.ObjProperty := "text";
 MyObject.ShowObjField;
end


Object"ы оставлены для совместимости с Borland Pascal"ем.

См. в справке: object types.


 
palva ©   (2005-03-13 22:54) [4]

По-моему, у объектов могут быть конструкторы, только их принято называть не Create а Init. Как давно это было...


 
default ©   (2005-03-13 23:09) [5]

palva ©   (13.03.05 22:54) [4]
да, могут, насколько я помню это нужно для объектов в которых используются динамически методы(dynamic, virtual)
в них иниц-ия нужная происходит для обеспечения работы механизма позднего связывания
вообщем всё это старо и автора сабжа лучше в голову это не брать


 
Defunct ©   (2005-03-14 05:15) [6]

> класс от объекта

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

1). Объявляем TRecord как Object:

TRecord = Object
 FirstName : String;
 LastName  : String;
 id        : Integer;

 function GetFullInfo:String;
end;
..
..

function TRecord.GetFullInfo;
begin
 Result := FirstName + " " + LastName + " (" +IntToStr(Age)+")";
end;
..
..
..
var
  Person : TRecord; // Память уже выделена под все поля TRecord
begin
 Person.FirstName := "lalala";
 Person.LastName := "blablabla";
 Person.id := 34;
 ShowMessage( Person.GetFullInfo );
end;


2). если объявить TRecord как класс, тогда..:

TRecord = class
 FirstName : String;
 LastName  : String;
 id        : Integer;

 function GetFullInfo:String;
end;
..
..

function TRecord.GetFullInfo;
begin
 Result := FirstName + " " + LastName + " (" +IntToStr(Age)+")";
end;
..
..
var
  Person : TRecord; // Person это указатель
begin
  Person := TPerson.Create; // Создать экземпляр (выделить память)
  try
     Person.FirstName := "lalala";
     Person.LastName := "blablabla";
     Person.id := 34;
     ShowMessage( Person.GetFullInfo );
  finally
     Person.Free  // Освободить выделенную память
  end
end;


Короче говоря, все еще есть область применения для Object. Хотя бы там где требуется просто сгруппировать множество локальных полей данных и методов работы с ними, и не заботиться об освобождении памяти: это значит, что если Object будет объявлен как локальная переменная какой-то функции, то память занимаемая им освободится на выходе из функции автоматически. Если же забыть разрушить экземпляр класса, то он так и останется висеть в памяти.

PS: если где ошибся, поправьте.


 
Defunct ©   (2005-03-14 05:23) [7]

begin...end ©   (13.03.05 22:07) [3]

Ерунду наговорили:

> У object"ов нет конструкторов и деструкторов.

неправда.
виртуальные методы были еще в TP6, а соответственно и конструкторы и деструкторы в объектах есть.


> А работать с ним можно так:
> var
>  MyObject: ^TMyObject;

Зачем с ним работать так? Если надо работать "так" так и создавать надо класс.


> или так:
> var
>   MyObject: TMyObject;

Только так, или вообще никак.


 
begin...end ©   (2005-03-14 09:51) [8]

> Defunct ©   (14.03.05 5:23) [7]

>> У object"ов нет конструкторов и деструкторов.
> неправда.
> виртуальные методы были еще в TP6, а соответственно и
> конструкторы и деструкторы в объектах есть.

Я имел в виду встроенные конструкторы и деструкторы. Их в object"ах действительно нет. Потому что у object"ов нет общего предка, в отличие от классов (для последних общим предком является TObject, в котором конструктор и деструктор уже есть). Ну а если Вы даже в этом сомневаетесь, - обратитесь к справке, она будет рада.

Разумеется, объявить конструктор можно и в object"е. Только в Delphi это объявление не нужно, понимаете? Да, в Турбо Паскале у объекта с виртуальными методами должен был быть конструктор/деструктор, и конструктор должен был вызываться, иначе ТВМ не была бы правильно настроена, и объект не работал бы. Вот пример из Паскаля:

program Objects;

type

 TFirstObject = object
   constructor Init;
   procedure MyProc; virtual;
 end;

 TSecondObject = object(TFirstObject)
   constructor Init;
   procedure MyProc; virtual;
 end;

 constructor TFirstObject.Init;
 begin
 end;

 constructor TSecondObject.Init;
 begin
 end;

 procedure TFirstObject.MyProc;
 begin
   WriteLn("1")
 end;

 procedure TSecondObject.MyProc;
 begin
   WriteLn("2")
 end;

var
 FObj: TFirstObject;
 SObj: TSecondObject;
begin
 FObj.Init;
 SObj.Init;

 FObj.MyProc;
 SObj.MyProc;
 ReadLn
end.


Заметьте - без вызовов конструкторов (выделенные строки) ничего нормально не работало бы.

А теперь вот аналогичный пример в Delphi:

program Objects;

{$APPTYPE CONSOLE}

uses
 SysUtils;

type

 TFirstObject = object
   procedure MyProc; virtual;
 end;

 TSecondObject = object(TFirstObject)
   procedure MyProc; virtual;
 end;

 procedure TFirstObject.MyProc;
 begin
   WriteLn("1")
 end;

 procedure TSecondObject.MyProc;
 begin
   WriteLn("2")
 end;

var
 FObj: TFirstObject;
 SObj: TSecondObject;
begin
 FObj.MyProc;
 SObj.MyProc;
 ReadLn
end.


И снова заметьте - никаких конструкторов нет и в помине, и, тем не менее, всё прекрасно работает. В отличие от Турбо Паскаля.

>>  MyObject: ^TMyObject;
> Зачем с ним работать так? Если надо работать "так" так
> и создавать надо класс.

Defunct, если Вам нужно динамически разместить в памяти какую-нибудь переменную - например, запись очень большого размера - Вы тоже, вместо того, чтобы использовать процедуры по выделению/освобождению памяти (New/Dispose или GetMem/FreeMem), превращаете record в class? Ну, в таком случае, мне Вас искренне жаль.

Причём я не говорил, что для object"ов нужно выделять память динамически. Я говорил, что это можно сделать. И так часто делали в том же Турбо Паскале. Более того: я даже не говорил, что с object"ами вообще нужно работать, и подчеркнул, что они оставлены только для обратной совместимости. А если object"ы переделывать в class"ы (как это предложили Вы) только потому, что память под них выделялась динамически - тогда нафиг вообще эта обратная совместимость нужна?


 
Defunct ©   (2005-03-14 11:01) [9]

begin...end ©   (14.03.05 09:51) [8]

> никаких конструкторов нет и в помине

то что вы их не объявили, не означает невозможность написания слова constructor. Ведь фраза "в типе record нет методов", трактуется однозначно. Разницу чуете?

> Defunct, если Вам нужно динамически разместить в памяти какую-нибудь переменную - например, запись очень большого размера - Вы тоже, вместо того, чтобы использовать процедуры по выделению/освобождению памяти (New/Dispose или GetMem/FreeMem), превращаете record в class?

Зависит от задачи, наиболее вероятно, что для размещения в памяти чего либо большого я воспользуюсь TMemoryStream.

> Ну, в таком случае, мне Вас искренне жаль.

Программа с обилием New/Dispose/GetMem/FreeMem разных каракулей типа шляпок и собачек на народном языке называется - глюкодром. Так что жалейте лучше себя.

> Причём я не говорил, что для object"ов нужно выделять память динамически. Я говорил, что это можно сделать. И так часто делали в том же Турбо Паскале.

Да, и именно это Ваше изречение поможет понять разницу между классом и объектом. Память можно выделить динамически под переменную любого типа, но не всегда это нужно. Общепринятую переменную i: integer предпочитают объявлять локально и не заботиться о выделении и освобождении памяти для нее. Точно также может возникнуть необходимость объединения небольшого кол-ва полей и методов работы с ними и не заботиться о выделении памяти под них (вот тут object и будет лучшим решением).


> А если object"ы переделывать в class"ы (как это предложили Вы) только потому, что память под них выделялась динамически -

Не переделывать, а сразу осознавая задачу и зная возможности использовать то, что больше всего подходит. Вы как раз лишаете, создавшего эту ветку, узнать возможности delphi.

Даете пример со шляпками New/Dispose, зачем оно надо? Если бы вопрос был про разницу между типом Integer и String почему бы не написать такой пример:

i : PInteger;

new(i);  
inc(i^);
dispose(i)

> тогда нафиг вообще эта обратная совместимость нужна?

Кому нужен потенциальный глюкодром? Глюкодром нужно избегать, а не поддерживать его. Иначе ж так и останется глюкодромом.


 
begin...end ©   (2005-03-14 11:30) [10]

> Defunct ©   (14.03.05 11:01) [9]

>> никаких конструкторов нет и в помине
>
> то что вы их не объявили, не означает невозможность
> написания слова constructor.

Разумеется. Вы можете объявить и вызвать в примере № 2 из [8] конструктор. Возможно, от этого Вам полегчает. Но пример будет работать точно так же, как и без конструктора. А зачем же его объявлять и вызывать, если и без него всё работает?

> Ведь фраза "в типе record нет методов", трактуется
> однозначно. Разницу чуете?

Я уже пояснил, что я говорил о встроенных конструкторах и деструкторах. Их в object"ах действительно нет. А фразу "в типе record нет методов" я не произносил, - Вы её придумали.

> Программа с обилием New/Dispose/GetMem/FreeMem разных
> каракулей типа шляпок и собачек на народном языке
> называется - глюкодром. Так что жалейте лучше себя.

Инструмент, допустивший много глюков в программе с New/Dispose на народном языке называется - кривые руки. Так что жалеть, всё-таки, следует именно Вас.

> Не переделывать, а сразу осознавая задачу и зная
> возможности использовать то, что больше всего
> подходит.

Э-э-э... Представьте, что в некоем старом исходнике из TP используются объекты, память под которые выделяется динамически. Так вот - я не понимаю, почему нужно переделывать весь код (превращать object в class, выбрасывать New и Dispose), когда можно оставить и так? А ведь Вы своей фразой из [7]: "Зачем с ним работать так? Если надо работать "так" так и создавать надо класс" именно такую переделку и предлагаете. Для того эта обратная совместимость и существует, чтобы ничего не переделывать, - по крайней мере, поначалу. А потом можно и переделать, но только не в статический object, а в class.

> Вы как раз лишаете, создавшего эту ветку, узнать
> возможности delphi.

Ни в коем случае. Автор может почитать данные ему советы и отфильтровать нужное для него, для его задачи. Даже без Вашей помощи. А ещё автор может заглянуть в справку, как ему и порекомендовали в [1]. Кстати, а Вы это уже сделали?


 
Defunct ©   (2005-03-14 12:12) [11]

> Разумеется. Вы можете объявить и вызвать в примере № 2 из [8] конструктор. Возможно, от этого Вам полегчает. Но пример будет работать точно так же, как и без конструктора. А зачем же его объявлять и вызывать, если и без него всё работает?

[8]
TFirstObject = object
  constructor Init;
  procedure MyProc; virtual;
end;

так есть конструктор или нет? Теперь читаем [3] "У object"ов нет конструкторов и деструкторов". теперь смотрим [8] - кто-то начал огрызаться, и на справку уповать.

> Я уже пояснил, что я говорил о встроенных конструкторах и деструкторах. Их в object"ах действительно нет.

Хотя мне честно сказать ваши пояснения совсем не нужны. Напомню что в [3] ничего не было пояснено.

> А фразу "в типе record нет методов" я не произносил, - Вы её придумали.

Все вам надо разжевывать.
Это моя фраза, и она верна, а ваша в [3] не верна, вот и разница.

> Инструмент, допустивший много глюков в программе с New/Dispose на народном языке называется - кривые руки.

Инструмент, допустивший много New/Dispose в программе на народном языке называется - кривые руки, а программа - глюкодромом. Так лучше звучит.


> Так что жалеть, всё-таки, следует именно Вас.
Бесплатную жалость в карман не положишь, высылайте пожертвования.

> Представьте, что в некоем старом исходнике из TP используются объекты, память под которые выделяется динамически.

Представил.

> Так вот - я не понимаю, почему нужно переделывать весь код (превращать object в class, выбрасывать New и Dispose), когда можно оставить и так?

Вообще-то при переносе из-под DOS в Win32 лучше пользоваться правилом - "выбрось и забудь". Также как и из Win32 в DOS.
А не поступать как предлагаете Вы - оставить. Оставить можно только глюкодром и потратить на него времени больше чем на написание нового модуля.

> А ведь Вы своей фразой из [7]: "Зачем с ним работать так? Если надо работать "так" так и создавать надо класс" именно такую переделку и предлагаете.

До сих пор не умеете читать? Или правда настолько зазубрились, что поверили собственному трактованию моей фразы? Я уже об этом вам сказал в [9].

> Для того эта обратная совместимость и существует, чтобы ничего не переделывать, - по крайней мере, поначалу. А потом можно и переделать, но только не в статический object, а в class.

Пять баллов. Так кто переделку предлагает? Вы в своих мыслях заблудились.

> Ни в коем случае. Автор может почитать данные ему советы и отфильтровать нужное для него, для его задачи. Даже без Вашей помощи. А ещё автор может заглянуть в справку, как ему и порекомендовали в [1].

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

> Кстати, а Вы это уже сделали?
Я что попугай?


 
begin...end ©   (2005-03-14 12:40) [12]

> Defunct ©   (14.03.05 12:12) [11]

> [8]
> TFirstObject = object
>  constructor Init;
>  procedure MyProc; virtual;
> end;

Перечитайте фразу, на которую отвечаете. Я говорил про пример [2]. Считать умеете?

> Напомню что в [3] ничего не было пояснено.

Это я и без Вас помню. Однако уже в [8] я это пояснил. Что же ещё нужно-то?

> Инструмент, допустивший много New/Dispose в программе
> на народном языке называется - кривые руки, а
> программа - глюкодромом. Так лучше звучит.

Как Вам будет угодно.

> Бесплатную жалость в карман не положишь, высылайте
> пожертвования.

На Ваше лечение? Боюсь, понадобится слишком много денег, а у меня их нет.

> Вообще-то при переносе из-под DOS в Win32 лучше
> пользоваться правилом - "выбрось и забудь". Также как
> и из Win32 в DOS.

Вообще-то в Win32 про object"ы следует вообще забыть. И именно потому, что они пока оставлены для обратной совместимости. Не удивлюсь, если скоро их выкинут. И на это недвусмысленно намекает Borland: "Object types are supported for backward compatibility only. Their use is not recommended.". Заметьте, что я ни разу не посоветовал их использовать, а Вы только это и делаете, напр.: "может возникнуть необходимость объединения небольшого кол-ва полей и методов работы с ними и не заботиться о выделении памяти под них (вот тут object и будет лучшим решением)".

> Я что попугай?

Нет, Вы просто не в себе.

---------------------------

И вообще, Defunct - я не вижу ни одной ошибки в [3], кроме отсутствия уточнения насчёт встроенных конструкторов. Это уточнение я уже сделал, поэтому смысла в обсуждении моих ошибок я не вижу. Потому что их здесь нет. К тому же, слушать чепуху, которую Вы несёте, мне уже поднадоело. Так что дальше можете разговаривать сами с собой. Удачи.


 
Defunct ©   (2005-03-14 13:12) [13]

> Перечитайте фразу, на которую отвечаете. Я говорил про пример [2]. Считать умеете?

А сами-то вы собственную фразу прочитали?
Там написано: "Вы можете объявить и вызвать в примере № 2 из [8] конструктор"
Вот я его объявил (пока что не вызывал). Мне полегчало (как там и было написано).
Вывод: вы просто непомните то, что пишете...

> Удачи.

Взаимно.


 
capkoh   (2005-03-14 21:20) [14]

Я понял, что ничего не понял!
Почитал справку, понял, что object"ы не рекомендуется использовать (ну и тут тоже писали) <что-то еще понял>, но главного так и не понял:

Зачем, все-таки, нужны "встроенные" в class методы (см. [0])?


 
jack128 ©   (2005-03-14 22:09) [15]

capkoh   (14.03.05 21:20) [14]
нужны "встроенные" в class методы (см. [0])?

Они не встроены, а унаследованы от одщего предка всех классов - TObject.
Эти методы осуществляют поддержку некоторых фич языка, касаемых классов, а именно: RTTI, динамическое распределение памяти под экземпляр класса, поддержка наследования от интерфейсов и обработка сообщений.


 
capkoh   (2005-03-14 22:25) [16]

Где можно об этом узнать подробнее?
Так, чтоб понятно было и все рассмотрено?


 
X_Tra   (2005-03-14 22:31) [17]

> Потому что у object"ов нет общего предка, в отличие от классов
> (для последних общим предком является TObject, в котором
> конструктор и деструктор уже есть)

Небольшое пояснение. Насколько я знаю, следующие два куска кода идентичны с точки зрения компилятора:


type TMyNewObject=class(TObject)
(...)
end



type TMyNewObject=class
(...)
end


А про то, зачем нужен TObject и его методы, можно прочитать в справке

> > Программа с обилием New/Dispose/GetMem/FreeMem разных
> > каракулей типа шляпок и собачек на народном языке
> > называется - глюкодром. Так что жалейте лучше себя.
> Инструмент, допустивший много глюков в программе с New/Dispose
> на народном языке называется - кривые руки. Так что жалеть,
> всё-таки, следует именно Вас.

Да, действительно, глюков в такой программе может быть много, но если всё аккуратно рассчитать, то ошибок не будет: проверено на собственном опыте:)


 
jack128 ©   (2005-03-14 22:43) [18]

capkoh   (14.03.05 22:25) [16]
Как ни странно, все расписано по F1


 
Дмитрий Мыльников   (2005-03-14 23:00) [19]

Встроенные в TObject методы нужны для получения информации о классе и его published свойствах во время работы программы (так называемый механизм RTTI - run time type information, который используется, в частности, в Object Inspector самой среды Deplhi).

И вообще, если ты не пользуешь старые прикладные библиотеки, которые писались ещё во времена Borland Pascal, то просто забудь про object и разбирайся с тем, как работает соврменная библиотека VCL. ИМХО, это более полезное занятие. :)



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

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

Наверх




Память: 0.56 MB
Время: 0.03 c
14-1110441448
ex080D:07BBh
2005-03-10 10:57
2005.03.27
По поводу того какие компутеры будут через 10 лет ))


1-1111075991
pisatell
2005-03-17 19:13
2005.03.27
IdRSH


1-1110493444
WST
2005-03-11 01:24
2005.03.27
И снова CheckBox


9-1100799849
Xerx
2004-11-18 20:44
2005.03.27
OpenGL, текстурирование и пересечения


3-1109064228
Aleksandr.
2005-02-22 12:23
2005.03.27
Не могу отладить создание таблицы в yaffil!