type TYac = {object}class private Znac:integer; public function GetZnac:integer; procedure PutZnac(z:integer); end;
TColumn = {object}class private Col:array[1..N] of TYac; public function GetZnac(i:integer):integer; procedure PutZnac(i,z:integer); end;
implementation
function TYac.GetZnac:integer; begin GetZnac:=Znac; end;
procedure TYac.PutZnac(z:integer); begin Znac:=z; end;
function TColumn.GetZnac(i:integer):integer; begin GetZnac:=col[i].GetZnac; end;
procedure TColumn.PutZnac(i,z:integer); begin col[i].PutZnac(z); end;
end.
Программа(Показать/Скрыть)
program Project1;
{$APPTYPE CONSOLE}
uses SysUtils, Unit1 in 'Unit1.pas';
var Column:TColumn;
begin Column.PutZnac(1,7); // Вот здесь ругается {Column.PutZnac(2,8); Column.PutZnac(3,5);} //writeln(Column.GetZnac(1)); // Вот здесь ругается readln; end.
А если писать object, то все норм.
Автор: volvo 28.03.2010 19:10
Класс обязан инициализироваться конструктором всегда. Для Object это не так (если нет виртуальных методов - конструктор можно не вызывать). Так что добавь
Column := TColumn.Create;
и наслаждайся
Автор: Unconnected 28.03.2010 19:12
Сначала ж надо вызвать конструктор объекта:)
Класс - это такой тип данных. А объект - экземпляр класса.
Добавлено через 1 мин. Чуть опоздал)
Автор: sheka 28.03.2010 19:27
Я уже Это пробовал после прочитки этой статьи http://e-dok.narod.ru/delphi/question1/opas/opas-004.html (других не нашел), не помогает.
Автор: Unconnected 28.03.2010 19:33
Так у тебя массив типа TYac, который является классом, следовательно, нужно вызывать конструктор для каждого элемента массива...
Автор: volvo 28.03.2010 19:51
Угу... Вот для этого и придумали конструкторы. Чтобы в момент конструирования TColumn тебе не пришлось заботиться о создании каждого элемента Col - сделай так:
Constructor TColumn.Create; begin Inherited Create; for i := 1 to N do Col[i] := TCol.Create; end;
Кстати, я бы заменил функции на property, чтоб было совсем хорошо
function TColumn.GetZnac(i:integer):integer; begin result := Col[i].Value; end; procedure TColumn.PutZnac(i,z:integer); begin Col[i].Value := z; end;
Не проще?
Можно и еще дальше пойти, и GetZnaс/PutZnaс в классе TColumn тоже на свойство поменять.
Автор: sheka 28.03.2010 19:52
Точно! Спасибо.
Добавлено через 4 мин. Я сделал именно так)))
constructor TColumn.Create; var i:integer; begin inherited; for i:=1 to N do Column[i]:=TYac.Create; end;
Только вместо Inherited Create; написал просто Inherited; . Какая между этими вариантами разница?
Автор: volvo 28.03.2010 20:11
Никакой разницы в данном случае не будет. Я обычно добавляю имя конструктора, хотя этого можно и не делать.
Цитата
Без параметров Inherited вызывает так же названный метод родительского класса, с теми же самыми параметрами.
Автор: sheka 28.03.2010 21:12
Пробую сделать свойствами:
type TCell = class private fValue:integer; function GetValue:integer; procedure PutValue(v:integer); published property Value:integer read GetValue write PutValue; end;
implementation
function TCell.GetValue:integer; begin result:=Value; end;
procedure TCell.PutValue(v:integer); begin Value:=v; end;
end.
Программа зависает. И когда
function GetValue:integer; procedure PutValue(v:integer);
ставлю в private, то вне модуля их не видно, а свойство Value видно.
Автор: volvo 28.03.2010 23:50
Цитата
Программа зависает.
Показывай, как вызываешь...
Цитата
ставлю в private, то вне модуля их не видно, а свойство Value видно.
Ну, это там и должно быть. Private - он на то и приватный, чтобы не быть видимым извне. Только изнутри. А Value у тебя published, поэтому и видимое отовсюду.
Автор: volvo 29.03.2010 0:30
Ух ты... Сразу не заметил... Ты чего ж делаешь?
function TCell.GetValue:integer; begin result:=fValue; // <-- У тебя был бесконечный рекурсивный вызов самого себя end; procedure TCell.PutValue(v:integer); begin fValue:=v; // <--- Аналогично end;
Ты же с помощью Геттера/Сеттера должен обращаться к полю, а не к свойству. А свойство работает через Геттер/Сеттер, а не напрямую с полем. Понимаешь, в чем преимущество? Вот ты сам написал, что методы GetValue/PutValue невидимы, так? И поле fValue тоже невидимо. Но в то же время свойство-то видимо, и обращаешься ты через него к невидимому полю посредством невидимой же функции.
Автор: Client 29.03.2010 0:39
Про то что можно описывать Object я даже и не знал... везде видел только class а про то что свойство можно вызывать рекурсивно - вообще не знал
Добавлено через 2 мин.
Цитата
А свойство работает через Геттер/Сеттер, а не напрямую с полем
Это ведь в данном случае, так как свойство описано с помощью процедуры и функции ?
Автор: volvo 29.03.2010 1:51
Цитата
Про то что можно описывать Object я даже и не знал...
Вообще-то использование Object-ов в Дельфи http://docwiki.embarcadero.com/RADStudio/en/Classes_and_Objects. Это устаревший тип, который не изменяется еще с Дельфи 4, если не ошибаюсь. Рекомендуется использовать либо Class, либо расширенные записи (начиная с D2006 записи могут иметь конструкторы, методы, и умеют перегружать операции).
Object оставлен для совместимости (ох уж эта совместимость...)
Автор: sheka 29.03.2010 2:47
Модуль(Показать/Скрыть)
unit Unit1;
interface
const N=1;
type TCell = class private fValue:integer; function GetValue:integer; procedure SetValue(v:integer); published property Value:integer read GetValue write SetValue; end;
TColumn = class private fColumn:array[1..N] of TCell; function GetCell(j:integer):TCell; procedure SetCell(j:integer;c:TCell); public constructor Create; property Column[j:integer]:TCell read GetCell write SetCell; end;
TRow = class private fRow:array[1..N] of TColumn; function GetColumn(i:integer):TColumn; procedure SetColumn(i:integer;c:TColumn); public //<--------------------------------вот здесь Published constructor Create; property Row[i:integer]:TColumn read GetColumn write SetColumn;
end;
TMatr = class(TRow) public procedure vvod(nam:string); procedure vivod(nam:string); end;
TFunc = class public function Mult(a,b:TMatr;N:byte):TMatr; end;
implementation
function TCell.GetValue:integer; begin result:=fValue; end;
procedure TCell.SetValue(v:integer); begin fValue:=v; end;
constructor TColumn.Create; var i:integer; begin inherited; for i:=1 to N do fColumn[i]:=TCell.Create; end;
function TColumn.GetCell(j:integer):TCell; begin result:=fColumn[j]; end;
procedure TColumn.SetCell(j:integer;c:TCell); begin fColumn[j]:=c; end;
constructor TRow.Create; var i:integer; begin inherited; for i:=1 to N do fRow[i]:=TColumn.Create; end;
function TRow.GetColumn(i:integer):TColumn; begin result:=fRow[i]; end;
procedure TRow.SetColumn(i:integer;c:TColumn); begin fRow[i]:=c; end;
procedure TMatr.vvod(nam:string); var i,j:byte; v:integer; begin for i:=1 to N do for j:=1 to N do begin write('vvedi ',nam,'[',i,',',j,']: '); readln(v); self.Row[i].Column[j].Value:=v; end; end;
procedure TMatr.vivod(nam:string); var i,j:byte; begin writeln(nam); for i:=1 to N do begin for j:=1 to N do write(self.Row[i].Column[j].Value:4); writeln; end; writeln; end;
function TFunc.Mult(a,b:TMatr;N:byte):TMatr; var i,j,s:byte; v:integer; begin for i:=1 to N do for j:=1 to N do begin v:=0; for s:=1 to N do begin //inc(v,a.Row[i].Column[s].Value*b.Row[s].Column[j].Value); //<---вот эти строчки не работают... //Mult.Row[i].Column[j].Value:=v; //<------------------------------- end; end; end;
end.
Программа(Показать/Скрыть)
program Project1;
{$APPTYPE CONSOLE}
uses SysUtils, Unit1 in 'Unit1.pas';
var a,b:TMatr; f:TFunc;
begin a:=TMatr.Create; a.vvod('a'); a.vivod('viv a'); b:=TMatr.Create; b.vvod('b'); b.vivod('viv b');
Не работают закомментированые строчки. Насколько я понял, это происходит из-за того, что "Published свойства не могут возвращать массивы." , а Publiс не видны "родственникам по программе" дальше чем потомки данного класса.
Добавлено через 8 мин. Извините, забыл. Задание: Найти произведение матриц.
Автор: volvo 29.03.2010 3:02
А может причина-таки в другом? Я ж говорил тебе, что каждый экземпляр класса должен быть создан. Вот и создавай:
function TFunc.Mult(a,b:TMatr;N:byte):TMatr; var i,j,s:byte; v:integer; begin result := TMatr.Create; // <--- Вот это за тебя кто делать будет?
for i:=1 to N do for j:=1 to N do begin v:=0; for s:=1 to N do begin inc(v,a.Row[i].Column[s].Value*b.Row[s].Column[j].Value); result.Row[i].Column[j].Value:=v; // <--- Чего тут у тебя не работало, говоришь? end; end; end;
Автор: sheka 29.03.2010 3:15
Да.. Не ожидал.
Автор: volvo 29.03.2010 16:28
sheka Ты думаешь это все, чего можно добиться Свойствами? Ошибаешься. Опиши оба свойства (и Column в классе TColumn, и Row в классе TRow) как Default, и тогда обращение к содержимому матрицы упростится:
function TFunc.Mult(a,b:TMatr;N:byte):TMatr; var i,j,s:byte; v:integer; begin result := TMatr.Create; for i:=1 to N do for j:=1 to N do begin v:=0; for s:=1 to N do begin // inc(v,a.Row[i].Column[s].Value*b.Row[s].Column[j].Value); // <---вот это inc(v,a[i][s].Value*b[s][j].Value); // <--- Может выглядеть так result[i][j].Value:=v; // <--- end; end; end;
Если свойство явно не вызывается, то считается что вызвано свойство с директивой default;? Вот нашел http://www.podgoretsky.com/ftp/Docs/Delphi/D5/dg/contents.html там даже для меня достаточно понятно описана работа со свойствами(другие разделы не читал). А на русском такой нет?
Автор: volvo 29.03.2010 18:30
А можно ссылку поправить? А то она у тебя какая-то усеченная, с многоточием в середине...
Автор: sheka 29.03.2010 19:54
Исправил.
Автор: volvo 29.03.2010 20:45
Именно эта - вряд ли есть. Но есть похожая: Стив Тейксейра и Ксавье Пачеко, "Руководство разработчика". Правда, она изрядно устарела, там описывается Дельфи 6.
Забрать можно здесь: http://www.delphilab.ru/content/view/17/46/