Felipe
Felipe

Reputation: 283

Component property derived from a custom class

I create my own class and I want to use it in my new component but I am getting an error... The code is the following:

type
  TMyClass = class
    Name: string;
    Number: double;
  end;

  TMyComponent = class(TCustomPanel)
  private
    FMyClass: TMyClass;
  public
    procedure SetMyClass(aName: string; aNumber: double);
  published
    property MyClass: TMyClass write SetMyClass;
  end;

procedure SetMyClass(aName: string; aNumber: double);
begin
  FMyClass.Name:= aName;
  FMyClass.Number:= aNumber;
end;

it appears that the property has incompatible types, I don't know why.

Does anybody has a clue about that and how can I solve this problem. Having a FName and FNumber as fields in TMyComponent is not an option, my code is more complex and this is a simple example to explain my goal.

thanks

Upvotes: 1

Views: 956

Answers (3)

Felipe
Felipe

Reputation: 283

unit MyComponentTest2;

interface

uses SysUtils, Classes, Controls, Forms, ExtCtrls, Messages, Dialogs;

type
  TMyClass = class
    Name: string;
    Number: double;
  end;

  TMyComponentTest2 = class(TCustomPanel)
  private
    FMyClass: TMyClass;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;

    procedure SetMyClass(Value: TMyClass);
  published
    property MyClass: TMyClass read FMyClass write SetMyClass;
  end;

procedure Register;

implementation

constructor TMyComponentTest2.Create(AOwner: TComponent);
begin
  Inherited Create(AOwner);
  FMyClass:= TMyClass.Create;
end;

destructor TMyComponentTest2.Destroy;
begin
  Inherited;
  FMyClass.Free;
end;

procedure TMyComponentTest2.SetMyClass(Value: TMyClass);
begin
  FMyClass.Name:= Value.Name;
  FMyClass.Number:= Value.Number;
end;

procedure Register;
begin
  RegisterComponents('MyComponents', [TMyComponentTest2]);
end;

end.

Upvotes: 0

David Heffernan
David Heffernan

Reputation: 612894

The things that I can see wrong with your code at present are:

  1. The property setter must receive a single parameter of the same type as the property, namely TMyClass.
  2. The property setter must be a member of the class, but you've implemented it as a standalone procedure.
  3. A published property needs to have a getter.

So the code would become:

type
  TMyClass = class
    Name: string;
    Number: double;
  end;

  TMyComponent = class(TCustomPanel)
  private
    FMyClass: TMyClass;
    procedure SetMyClass(Value: TMyClass);
  published
    property MyClass: TMyClass read FMyClass write SetMyClass;
  end;

procedure TMyComponent.SetMyClass(Value: TMyClass);
begin
  FMyClass.Name:= Value.Name;
  FMyClass.Number:= Value.Number;
end;

This code does not instantiate FMyClass. I'm guessing that the code that does instantiate FMyClass is part of the larger component code that has been excised for the sake of this question. But obviously you do need to instantiate FMyClass.

An alternative to instantiating FMyClass is to turn TMyClass into a record. Whether or not that would suit your needs I cannot tell.


It looks like you are having some problems instantiating this object. Do it like this:

type
  TMyClass = class
    Name: string;
    Number: double;
  end;

  TMyComponent = class(TCustomPanel)
  private
    FMyClass: TMyClass;
    procedure SetMyClass(Value: TMyClass);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property MyClass: TMyClass read FMyClass write SetMyClass;
  end;

constructor TMyComponent.Create(AOwner: TComponent);
begin
  inherited;
  FMyClass:= TMyClass.Create;
end;

destructor TMyComponent.Destroy;
begin
  FMyClass.Free;
  inherited;
end;

procedure TMyComponent.SetMyClass(Value: TMyClass);
begin
  FMyClass.Name:= Value.Name;
  FMyClass.Number:= Value.Number;
end;

One final comment. Using MyClass for an object is a bad name. Use class for the type, and object for the instance. So, your property should be MyObject and the member field should be FMyObject etc.

Upvotes: 2

David Miró
David Miró

Reputation: 2758

Try this:

type
  TMyClass = class
    Name: string;
    Number: double;
  end;

  TMyComponent = class(TCustomPanel)
  private
    FMyClass: TMyClass;
  public
    procedure SetMyClass(Value: TMyClass);
  published
    property MyClass: TMyClass write SetMyClass;
  end;

procedure TMyComponent.SetMyClass(Value);
begin
  FMyClass := Value;
end;

Upvotes: 1

Related Questions