Results 1 to 8 of 8

Thread: Inheriting Classes? *solved*

  1. #1

    Inheriting Classes? *solved*

    If I have a class which has a method which takes a second class as an parameter. And then I have third class which is inherited from second, so it contains same methods as second one does. Now if I want to pass that third class to the method of the first class. How to implement that method so it accepts a class and all it's descendants?

    for example...

    Code:
    TFirstClass = Class
    private
    public
       procedure Dosomething(AClass: ???????);       // How to do this so it accepts
    end;                                             //the second and all its descentand classes?
    
    
    TSecondClass = Class
    private
    public
       procedure DoSomething;
    end;
    
    
    TThirdClass = Class(TSecondClass)                  // Notice inheritance.
    private
    public
       procedure DoSomethingElse;
    end;
    
    var
      FirstClass: TFirstClass;
      3rdClass:  TThirdClass;
     
         .
         .
         .
    
    procedure SomeProcedureSomewhere;
    begin
      FirstClass.DoSomething(3rdClass);
    end;
    How to implement something like that?
    - In a world without the wall and fences, who will need the Gates and Windows.

  2. #2

    Re: Inheriting Classes?

    Code:
    type
    
    TSecondClass = Class;
    
    TFirstClass = Class
    private
    public
       procedure Dosomething(AClass: TSecondClass);       // How to do this so it accepts
    end;                                             //the second and all its descentand classes?
    
    
    TSecondClass = Class
    private
    public
       procedure DoSomething;
    end;
    
    
    TThirdClass = Class(TSecondClass)                  // Notice inheritance.
    private
    public
       procedure DoSomethingElse;
    end;
    There are only 10 types of people in this world; those who understand binary and those who don't.

  3. #3

    Re: Inheriting Classes?

    Thank you Clootie for your answer but I forgot to mention that firstclass DoSomething() method initializes that class which is passed in method. So it should be var parameter.

    Like this....

    Code:
    TFirstClass = Class
    private
    public
       procedure Dosomething(var AClass: ???????);       // How to do this so it accepts
    end;                                                 //the second and all its descentand classes?
    
    
    TSecondClass = Class
    private
    public
       procedure DoSomething;
    end;
    
    
    TThirdClass = Class(TSecondClass)                  // Notice inheritance.
    private
    public
       procedure DoSomethingElse;
    end;
    
    var
      FirstClass: TFirstClass;
      3rdClass:  TThirdClass;
     
    
    procedure TFirstClass.DoSomething(var AClass: ?????????);
    begin
       AClass := ???????(AClass).create;      // or something like that??
    end;
    
        .
        .
        .
    
    procedure SomeProcedureSomewhere;
    begin
      FirstClass.DoSomething(3rdClass);
    end;
    Or how I should do something like this. All I get now is compiler error: "Types of actual and formal var parameters must be identical." at the line inside SomeProcedureSomewhere().

    Edit: please help me with this. This is very important for my game engine.
    - In a world without the wall and fences, who will need the Gates and Windows.

  4. #4

    Re: Inheriting Classes?

    You cannot do that as you said. If you use the var parameter, the types must be the same. (and it's obvious, since otherway you could break the type system, putting a SecondClass instance in a ThirdClass object)

    If you need to initialize the class, you should do something like:

    function Dosomething():TSecondClass;

    where you can return whatever descendant of TSecondClass.
    If you save your data in a proprietary format, the owner of the format owns your data.
    <br /><A href="http://msx80.blogspot.com">http://msx80.blogspot.com</A>

  5. #5

    Re: Inheriting Classes?

    Quote Originally Posted by {MSX}
    You cannot do that as you said. If you use the var parameter, the types must be the same. (and it's obvious, since otherway you could break the type system, putting a SecondClass instance in a ThirdClass object)

    If you need to initialize the class, you should do something like:

    function Dosomething():TSecondClass;

    where you can return whatever descendant of TSecondClass.
    Okey, thanks. But does that execute constructor of descentand? I mean if i introduce a constructor in the TThirdClass and then try to create instance of it with that DoSomething function which returns instance of TSecondClass?

    edit: what I try to do is this -> http://tonyandpaige.com/tutorials/game1.html


    edit2: I just build up a little test program which works fine except that constructor of descentant classes is never ran. Here's the code.

    This is in own unit file....

    [pascal]
    unit uGameStates;

    interface

    uses
    Classes;

    type
    TStateClass = Class
    public
    constructor Create;
    destructor Destroy; override;
    end;

    type
    TManagerClass = Class(Tlist)
    public
    procedure ChangeState(State: TStateClass);
    constructor Create;
    destructor Destroy; override;
    end;

    implementation

    { TStateClass }

    constructor TStateClass.Create;
    begin

    end;

    destructor TStateClass.Destroy;
    begin

    inherited;
    end;

    { TManagerClass }

    constructor TManagerClass.Create;
    begin
    inherited Create;
    end;

    destructor TManagerClass.Destroy;
    var
    Index: Integer;
    begin
    for Index := 0 to Pred(Count) do begin
    TStateClass(Items[0]).Free;
    Delete(0);
    end;
    inherited;
    end;

    procedure TManagerClass.ChangeState(State: TStateClass);
    begin
    if Self.Count > 0 then begin
    TStateClass(Items[0]).Free;
    Delete(0);
    end;
    State := TStateClass.Create;
    Self.Add(State);
    end;
    end.
    [/pascal]

    And here's the main unit (a form with a button)....

    [pascal]
    unit uMain;

    interface

    uses
    Forms, Classes, Controls, StdCtrls, uGameStates;

    type
    TForm1 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    private
    public
    end;

    type
    TLevel1 = class(TStateClass)
    private
    FOldCapt: String;
    public
    constructor create;
    destructor destroy; override;
    end;

    var
    Form1: TForm1;
    StateManager: TManagerClass;
    Level1: TLevel1;

    implementation
    {$R *.dfm}

    { TForm1 }

    procedure TForm1.FormCreate(Sender: TObject);
    begin
    StateManager := TManagerClass.Create;
    end;

    procedure TForm1.FormDestroy(Sender: TObject);
    begin
    StateManager.Free;
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    begin
    StateManager.ChangeState(Level1);
    end;

    { TLevel1 }

    constructor TLevel1.create;
    begin
    inherited Create;
    FOldCapt := Form1.Caption;
    Form1.Caption := 'Yes, it''s works!';
    end;

    destructor TLevel1.destroy;
    begin
    Form1.Caption := FOldCapt;
    inherited;
    end;
    end.
    [/pascal]

    When button on the form is pressed StateManager.ChangeState() method is ran with Level1 as an parameter. Then ChangeState() method should ran constructor of TLevel1 and store class to TList (manager itself). And when manager changes state again (not in this example) previous state is freed and new state stored in manager. So, then TLevel1.Destroy() method should be called.

    And like I said works fine except TLevel1.Constructor is never ran. How to do this right?
    - In a world without the wall and fences, who will need the Gates and Windows.

  6. #6

    Inheriting Classes? *solved*

    Umm your code is wrong in various place
    First, it never calls TLevel constructor becouse you never call TLevel.create.
    You call TStateClass.create, which creates only TStateClass.
    Also, if you pass an object to a procedure without the var clausule, and you reassign the parameter with a new object, the new object is not avaiable on the caller side. So your TLevel1 is unassigned at the Button1Click, and the TStateClass created is lost (and you have a memory leak).
    If you save your data in a proprietary format, the owner of the format owns your data.
    <br /><A href="http://msx80.blogspot.com">http://msx80.blogspot.com</A>

  7. #7

    Inheriting Classes? *solved*

    [pascal]
    TStateClass = Class
    public
    constructor Create; virtual;
    destructor Destroy; override;
    end;

    TClassOfState = class of TStateClass;

    TLevel1 = class(TStateClass)
    private
    FOldCapt: String;
    public
    constructor create; override;
    destructor destroy; override;
    end;

    procedure TManagerClass.ChangeState(out State: TStateClass; StateClass: TClassOfState);
    begin
    ....
    State := StateClass.Create;
    Self.Add(State);
    end;
    [/pascal]
    There are only 10 types of people in this world; those who understand binary and those who don't.

  8. #8

    Inheriting Classes? *solved*

    Quote Originally Posted by {MSX}
    Umm your code is wrong in various place
    First, it never calls TLevel constructor beco...<snip>
    Yea, yea, yea I know, but you ain't helping me either :?


    CLOOTIE! You're the best! It works now. Thank you SOOOOOOO much! Grab a cup of coffee and lean back. I'll treat .

    edit: Here is the final code of this simple example of mine. If someone is doing something similar.....

    Unit uStateManager.
    [pascal]
    unit uStateManager;

    interface

    uses
    Classes;

    type
    TStateClass = Class
    public
    constructor Create; virtual;
    destructor Destroy; override;
    end;

    TClassOfState = Class of TStateClass;

    type
    TManagerClass = Class(Tlist)
    public
    procedure ChangeState(out State: TStateClass; StateClass: TClassOfState);
    constructor Create;
    destructor Destroy; override;
    end;

    implementation

    { TStateClass }

    constructor TStateClass.Create;
    begin
    end;

    destructor TStateClass.Destroy;
    begin
    inherited;
    end;

    { TManagerClass }

    constructor TManagerClass.Create;
    begin
    inherited Create;
    end;

    destructor TManagerClass.Destroy;
    var
    Index: Integer;
    begin
    for Index := 0 to Pred(Count) do begin
    TStateClass(Items[0]).Free;
    Delete(0);
    end;
    inherited;
    end;

    procedure TManagerClass.ChangeState(out State: TStateClass; StateClass: TClassOfState);
    begin
    if Self.Count > 0 then begin
    TStateClass(Items[0]).Free;
    Delete(0);
    end;
    State := StateClass.Create;
    Self.Add(State);
    end;
    end.
    [/pascal]

    Main module.
    [pascal]
    unit uMain;

    interface

    uses
    Forms, Classes, Controls, StdCtrls, uStateManager;

    type
    TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    private
    public
    end;

    type
    TLevel1 = class(TStateClass)
    private
    FOldCapt: String;
    public
    constructor create; override;
    destructor destroy; override;
    end;

    type
    TLevel2 = Class(TLevel1)
    public
    constructor create; override;
    end;

    var
    Form1: TForm1;
    StateManager: TManagerClass;
    Level1: TStateClass;
    Level2: TStateClass;

    implementation
    {$R *.dfm}

    { TForm1 }

    procedure TForm1.FormCreate(Sender: TObject);
    begin
    StateManager := TManagerClass.Create;
    end;

    procedure TForm1.FormDestroy(Sender: TObject);
    begin
    StateManager.Free;
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    begin
    StateManager.ChangeState(Level1, TLevel1);
    end;

    procedure TForm1.Button2Click(Sender: TObject);
    begin
    StateManager.ChangeState(Level2, TLevel2);
    end;

    { TLevel1 }

    constructor TLevel1.create;
    begin
    FOldCapt := Form1.Caption;
    Form1.Caption := 'Level1 Loaded...';
    end;

    destructor TLevel1.destroy;
    begin
    Form1.Caption := FOldCapt;
    inherited;
    end;

    { TLevel2 }

    constructor TLevel2.create;
    begin
    FOldCapt := Form1.Caption;
    Form1.Caption := 'Level2 Loaded...';
    end;
    end.
    [/pascal]
    - In a world without the wall and fences, who will need the Gates and Windows.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •