Dauezevy
Dauezevy

Reputation: 1080

Delphi property stackoverflow error

My Property Class:

unit SubImage;

interface

type
TSubImage = class
private
  { private declarations }
  function getHeight: Integer;
  function getWidth: Integer;
  procedure setHeight(const Value: Integer);
  procedure setWidth(const Value: Integer);
protected
  { protected declarations }
public
  { public declarations }
  property width : Integer read getWidth write setWidth;
  property height : Integer read getHeight write setHeight;
published
  { published declarations }
end;
implementation

{ TSubImage }

function TSubImage.getHeight: Integer;
begin
  Result:= height;
end;

function TSubImage.getWidth: Integer;
begin
  Result:= width;
end;

procedure TSubImage.setHeight(const Value: Integer);
begin
  height:= Value;
end;

procedure TSubImage.setWidth(const Value: Integer);
begin
  width:= Value;
end;

end.

Assignment:

objSubImg.width:= imgOverview.width;
objSubImg.height:= imgOverview.heigh

Interesting Error:

stackoverflow at xxxxxx

I am learning to properties in Delphi. I created a class, but it gives an error. I couldn't understand, where is my mistake?

Also i dont understand why we use property instead of setter/getter methods. Anyway can someone help me, how can i fix this code ?

I can not set property value.

Upvotes: 7

Views: 1263

Answers (1)

David Heffernan
David Heffernan

Reputation: 612884

This is a non terminating recursion. The getter looks like this:

function TSubImage.getHeight: Integer;
begin
  Result := height;
end;

But height is the property. So the compiler re-writes this as:

function TSubImage.getHeight: Integer;
begin
  Result := getHeight;
end;

And that's a non-terminating recursion. Hence the stack overflow.

You need to declare fields to store the values:

type
  TSubImage = class
  private
    FHeight: Integer;
    FWidth: Integer;
    function getHeight: Integer;
    function getWidth: Integer;
    procedure setHeight(const Value: Integer);
    procedure setWidth(const Value: Integer);
  public
    property width: Integer read getWidth write setWidth;
    property height: Integer read getHeight write setHeight;
  end;

And then get and set the values:

function TSubImage.getHeight: Integer;
begin
  Result:= FHeight;
end;

procedure TSubImage.setHeight(const Value: Integer);
begin
  FHeight:= Value;
end;

And likewise for the other property.

In this simple example you don't need to use getter and setter functions. You could declare the properties like this:

property width: Integer read FWidth write FWidth;
property height: Integer read FHeight write FHeight;

But I guess you know that and are exploring how getter/setter functions work.

As for why we use properties rather than getter and setter functions, that comes down to clarity and readability of code. You can replace properties with getter and setter functions. After all, that's all that the compiler does. But it is often clearer to write:

h := obj.Height;
obj.Height := h*2;

than

h := obj.GetHeight;
obj.SetHeight(h*2);

Upvotes: 6

Related Questions