Модераторы: Poseidon, Snowy, bems, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Константы в классе 
V
    Опции темы
superVad
Дата 12.7.2011, 23:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 735
Регистрация: 6.4.2006
Где: Черкассы, Украина

Репутация: 4
Всего: 15



У меня в классе должны быть неизменяемые во время работы объекта константы.

Как правильнее реализовать:
1) Инициализировать поле во время создания объекта и отдавать его свойством.
2) Просто возвращать функцией.

Да и - Делфи 7.

Это сообщение отредактировал(а) superVad - 12.7.2011, 23:05
PM MAIL   Вверх
Akella
Дата 12.7.2011, 23:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 36
Всего: 329



А просто объявить константы нельзя?
Const
 a = 10;
 b = 20;
PM MAIL   Вверх
superVad
Дата 12.7.2011, 23:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 735
Регистрация: 6.4.2006
Где: Черкассы, Украина

Репутация: 4
Всего: 15



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

Может само слово константа не правильно подобрано...
PM MAIL   Вверх
northener
Дата 13.7.2011, 00:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 8
Всего: 20



Цитата(superVad @  12.7.2011,  23:30 Найти цитируемый пост)
есть родительский класс, его потомки отличаются некоторыми "константами". Но в самом классе константу не объявить.

Может само слово константа не правильно подобрано


Наверно неправильно. Потомки класса не должны отличаться друг от друга только некоторой "константой",  которую можно "отдавать как свойство" (у них и так разные классы) или результатом некоей функции предка.
Имхо стоит немножко приблизить данную задачу к "Задаче Х" с одновременным удалением от "Задачи Y".
P.S. Соответствующую сагу ты должен знать. smile


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
superVad
Дата 13.7.2011, 00:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 735
Регистрация: 6.4.2006
Где: Черкассы, Украина

Репутация: 4
Всего: 15



Цитата(northener @  12.7.2011,  23:10 Найти цитируемый пост)
аверно неправильно. Потомки класса не должны отличаться друг от друга только некоторой "константой",  которую можно "отдавать как свойство" (у них и так разные классы) или результатом некоей функции предка.Имхо стоит немножко приблизить данную задачу к "Задаче Х" с одновременным удалением от "Задачи Y".P.S. Соответствующую сагу ты должен знать. 


Ну ладно, классы отличаются еще и некоторыми методами. smile

Но все же:
1) Инициализировать поле во время создания объекта и отдавать его свойством.
2) Просто возвращать функцией:
Код

function some_class.get_some_field: Integer;
begin
  Result := 123;
end;


Это сообщение отредактировал(а) superVad - 13.7.2011, 00:25
PM MAIL   Вверх
northener
Дата 13.7.2011, 00:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 8
Всего: 20



Цитата(superVad @  13.7.2011,  00:24 Найти цитируемый пост)
Ну ладно, классы отличаются еще и некоторыми методами.

Ты меня не понял. Классы - потомки некоего класса отличаются уж тем, что они - суть разные классы!
Код

TMyClass = class()
...
end;

TFirstChildOfMyClass = class(TMyClass)
...
end;

TSecondChildOfMyClass = class(TMyClass)
...
end;


TFirstChildOfMyClass и TSecondChildOfMyClass - разные классы. И оператор Is примененный к экземплярам(объектам) данных классов это подтвердит.

Добавлено через 2 минуты и 20 секунд
Цитата(superVad @  13.7.2011,  00:24 Найти цитируемый пост)
Но все же:
1) Инициализировать поле во время создания объекта и отдавать его свойством.

И всё же я напоминаю про сагу.


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
Keeper89
Дата 13.7.2011, 01:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2580
Регистрация: 26.2.2009

Репутация: 20
Всего: 58



superVad, 
приведи примеры классов, думаю так всем понятнее будет


--------------------
PM MAIL WWW   Вверх
northener
Дата 13.7.2011, 01:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 8
Всего: 20



А ещё лучше озвучь задачу, для которой тебе нужны "константы в классе".


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
superVad
Дата 13.7.2011, 09:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 735
Регистрация: 6.4.2006
Где: Черкассы, Украина

Репутация: 4
Всего: 15



Это связано с отчетами.
В родителе находятся всякие общие для всех отчетов методы.
Потомки отличаются как способом подсчета данных, так и в них должны быть - количество колонок, их названия, запросы... И эти данные не меняются во время работы методов объекта. Как их правильней объявить.
PM MAIL   Вверх
Akella
Дата 13.7.2011, 09:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 36
Всего: 329



Цитата(superVad @  12.7.2011,  23:30 Найти цитируемый пост)
Может само слово константа не правильно подобрано... 

да, по идее константа - это Const smile

Добавлено через 35 секунд
А если объявить свойство только read? Тогда его изменить извне нельзя будет.
PM MAIL   Вверх
superVad
Дата 13.7.2011, 10:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 735
Регистрация: 6.4.2006
Где: Черкассы, Украина

Репутация: 4
Всего: 15



Цитата(Akella @  13.7.2011,  08:49 Найти цитируемый пост)
А если объявить свойство только read? Тогда его изменить извне нельзя будет.

Возвращаемое функцией значение тоже как бы изменить сложно smile

По мне первый вариант выглядит как то правильней. Но во втором можно сделать методы класса и обращаться к ним без создания объекта, если надо конечно.
PM MAIL   Вверх
1000000dollars
Дата 13.7.2011, 12:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 231
Регистрация: 6.10.2007

Репутация: нет
Всего: 8



Я бы сделал свойством. Примерно так:
Код

    C_Base = class
        protected
            function  getMagicConst: integer; virtual; abstract;

        public
            property MagicConst: integer read getMagicConst;
        end;

    C_Other = class(C_Base)
        protected
            function getMagicConst(): integer; virtual; overload;
        end;

    C_Another = class(C_Base)
        private:
            magic_x, magic_y: integer;
        public
            function getMagicConst(): integer; virtual; overload;
        end;

function C_Other.getMagicConst():integer;
begin
    result := 42;
end;

function C_Another.getMagicConst():integer;
begin
    result := magic_x+magic_y;
end;


интерфйс фиксирован, а значение хочешь константное, хочешь вычисляемое и всё прозрачно smile

PS: делфи под рукой нет и давно на нём не писал - так что могут быть ошибки.
PM MAIL   Вверх
superVad
Дата 13.7.2011, 12:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 735
Регистрация: 6.4.2006
Где: Черкассы, Украина

Репутация: 4
Всего: 15



1000000dollars, спасибо за совет. Похоже на вариант 2, но значение функции читается через свойство, что мне кажется излишне.
PM MAIL   Вверх
de_Nis
Дата 13.7.2011, 12:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Старательный
*


Профиль
Группа: Участник
Сообщений: 223
Регистрация: 19.10.2006
Где: Молдова

Репутация: нет
Всего: 6



Возможно, это прописные истины, но все же:
1) Если все классы в одном модуле, константы можно объявить в разделе implementation этого модуля.
2) Можно выделить константы в отдельный модуль, подключаемый при необходимости.


Это сообщение отредактировал(а) de_Nis - 13.7.2011, 13:07
--------------------
Несчастлив не тот, у кого ничего нет, а тот, кто ничего не хочет…
PM   Вверх
Keeper89
Дата 13.7.2011, 13:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2580
Регистрация: 26.2.2009

Репутация: 20
Всего: 58



Вечером постараюсь набросать маленький вариант

Это сообщение отредактировал(а) Keeper89 - 13.7.2011, 20:42


--------------------
PM MAIL WWW   Вверх
bems
Дата 13.7.2011, 14:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 31
Всего: 88



Если "константы" используются базовым классом, а переопределяются в потомках, то тут только виртуальная функция


--------------------
Обижено школьников: 8
PM MAIL   Вверх
superVad
Дата 13.7.2011, 15:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 735
Регистрация: 6.4.2006
Где: Черкассы, Украина

Репутация: 4
Всего: 15



Цитата(bems @  13.7.2011,  13:55 Найти цитируемый пост)
Если "константы" используются базовым классом, а переопределяются в потомках, то тут только виртуальная функция

Ну можно еще же инициализировать поля в Create потомков, а потом поставить inherited.
PM MAIL   Вверх
1000000dollars
Дата 13.7.2011, 15:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 231
Регистрация: 6.10.2007

Репутация: нет
Всего: 8



Цитата(superVad @  13.7.2011,  12:29 Найти цитируемый пост)
значение функции читается через свойство


Я же объяснил зачем так - всё ради гибкости решения smile
PM MAIL   Вверх
superVad
Дата 13.7.2011, 15:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 735
Регистрация: 6.4.2006
Где: Черкассы, Украина

Репутация: 4
Всего: 15



Цитата(1000000dollars @  13.7.2011,  14:16 Найти цитируемый пост)
Я же объяснил зачем так - всё ради гибкости решения 

Не совсем понятно в чем гибкость. В коде этого не видно - можно же спокойно обращаться к функции в обоих потомках.
Может не уловил чего smile
PM MAIL   Вверх
Keeper89
Дата 13.7.2011, 20:43 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2580
Регистрация: 26.2.2009

Репутация: 20
Всего: 58



superVad, вот пример
Код

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils, classes;

type
  TClass1 = class
  private
    FFields: TStringList;
    FSQL: string;
    procedure SetInitialValues; virtual;
  public
    constructor Create;
    destructor Destroy; override;
    function ToString: string;
    property Fields: TStringList read FFields;
    property SQL: string read FSQL;
  end;

  TClass2 = class(TClass1)
  private
    procedure SetInitialValues; override;
  end;

{ Class1 }

constructor TClass1.Create;
begin
  FFields := TStringList.Create;
  SetInitialValues;
end;

destructor TClass1.Destroy;
begin
  inherited;
  FreeAndNil(FFields);
end;

procedure TClass1.SetInitialValues;
begin
  FFields.Add('ID0');
  FFields.Add('ID1');
  FSQL := 'SELECT FROM...';
end;

function TClass1.ToString: string;
begin
  Result := ClassName + #13#10 +
            'SQL = ' + FSQL + #13#10 +
            'Fields = ' + FFields.CommaText;
end;

{ Class2 }

procedure TClass2.SetInitialValues;
begin
  FFields.Add('ID2');
  FFields.Add('ID3');
  FSQL := 'DELETE FROM...';
end;

begin
  with TClass1.Create do
    try
      Writeln(ToString);
    finally
      Free;
    end;
  Writeln;
  with TClass2.Create do
    try
      Writeln(ToString);
    finally
      Free;
    end;
  Readln;
end.

если неправильно понял - жду пояснений smile

Это сообщение отредактировал(а) Keeper89 - 13.7.2011, 20:44


--------------------
PM MAIL WWW   Вверх
1000000dollars
Дата 14.7.2011, 10:24 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 231
Регистрация: 6.10.2007

Репутация: нет
Всего: 8



Цитата(superVad @  13.7.2011,  15:45 Найти цитируемый пост)
Не совсем понятно в чем гибкость.


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

Получается, что клиенты классов получают константное значение (чего они и ожидают), а объект отдаёт значение, согласующееся с его логикой.

В примере ниже три класса:  таблица (базовый класс), статическая таблица (количество строк реально константное) и динамическая таблица (количество строк вычисляется).

В массив из таблиц помещаю и статические и динамические таблицы, и при последующем обращении получаю корректное значение количества строк - для статических - их статическую константу, для динамических - текущее значение.

Если всё сделать через метод, то в базовом классе (C_Table) придётся заводить специальное поле, инициализировать его и писать метод, возвращающий его значение (в случае C_StaticTable можно обойтись без этого) - а это лишний код, лишний расход памяти и времени выполнения.

Код

program Project2;

{$APPTYPE CONSOLE}

uses
 SysUtils;

type
    C_Table = class
        protected
            function  getRowCount: integer; virtual; abstract;

        public
            property RowCount: integer read  getRowCount;
        end;

    C_StaticTable = class(C_Table)
        protected
            function getRowCount: integer; override;
        end;

    C_DynamicTable = class(C_Table)
        private
            _rows : integer;
        public
            function getRowCount: integer; override;
            procedure AddRow;
        end;

procedure C_DynamicTable.AddRow;
begin
    inc(_rows);
end;

function C_StaticTable.getRowCount:integer;
begin
    result := 42;
end;

function C_DynamicTable.getRowCount:integer;
begin
    result := _rows;
end;

var
    tables: array [0..3] of C_Table;
    stat: C_StaticTable;
    Dyn: C_DynamicTable;
    i : integer;

begin
    stat := C_StaticTable.Create;
    tables[0] := stat;

    stat := C_StaticTable.Create;
    tables[1] := stat;

    Dyn := C_DynamicTable.Create;
    Dyn.AddRow;
    Dyn.AddRow;
    tables[2] := Dyn;

    Dyn := C_DynamicTable.Create;
    Dyn.AddRow;
    Dyn.AddRow;
    Dyn.AddRow;
    Dyn.AddRow;
    tables[3] := Dyn;

    for  i:=Low(tables) to High(tables)do
        WriteLn(tables[i].RowCount);
    readLn;

end.


Добавлено через 4 минуты и 33 секунды
Keeper89, на тех же классах

Код

var
 c1 : TClass1;

begin

  c1 := TClass1.Create;
  WriteLn(  c1.ToString);
  C1.FFields.Add('Really const? ;)');
  WriteLn(  c1.ToString);

  Readln;
end.

PM MAIL   Вверх
superVad
Дата 14.7.2011, 11:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 735
Регистрация: 6.4.2006
Где: Черкассы, Украина

Репутация: 4
Всего: 15



Цитата(1000000dollars @  14.7.2011,  09:24 Найти цитируемый пост)
Если всё сделать через метод, то в базовом классе (C_Table) придётся заводить специальное поле, инициализировать его и писать метод, возвращающий его значение (в случае C_StaticTable можно обойтись без этого) - а это лишний код, лишний расход памяти и времени выполнения.

Не уловил. Может из-за жары - но не понятно, что это за поле в базовом классе, зачем его инициализировать...

В общем я согласен - лучше использовать свойства. Они дают какую то дополнительную абстракцию, в будущем для внесения изменений может пригодится. Но я не понял именно твоей аргументации smile

Добавлено @ 11:14
Спасибо всем за помощь. Главное, что для себя я осознал, что этот вопрос можно решить 2 способами - в принципе равнозначными.
1) Keeper89 Инициализировать поля в конструкторе виртуальным методом (или прямо в конструкторе, перекрывая его).
2) 1000000dollars Возвращать значения виртуальными функциями. Формально это даже правильнее, т.к. эти значения точно не изменяемые.

Ну и естественно все это делать надо через свойства. smile

ПС Как подсказал CodeMonkey в более новых Делфи уже реализованы классовые константы. Жаль в 7 их еще нет :(

Это сообщение отредактировал(а) superVad - 14.7.2011, 11:16
PM MAIL   Вверх
Чучмек
Дата 17.7.2011, 14:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


НЭТ БИЛЭТ
**


Профиль
Группа: Участник
Сообщений: 841
Регистрация: 11.5.2008
Где: СССР

Репутация: 14
Всего: 41



Цитата(superVad @  14.7.2011,  11:07 Найти цитируемый пост)
 Формально это даже правильнее,

А заполни массив такой "константой",и сравни время заполнения. 


--------------------
умную мысль держи при себе, а дурной - поделись с другими 
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0816 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.