21.12.2010 3:37, Sven Barth wrote:

Especially at the core devs, but maybe also for other interested persons
I have the following questions regarding the implementation of this
feature:
- should class helpers have access to protected fields of the extended
class? I propose not or this would beat the complete idea of "sealed" (I
also believe that Delphi doesn't allow it as well)

Protected, strict protected and private but not strict private.

- should class helpers be able to be instantiated or even referenced in
any way? (including forward declarations)

no

- should class helpers be allowed to override/reintroduce methods?

reintroduce - yes, but since class helper is not a child class using reitroduce does not do anything.

- should class helpers be able to extend other class helpers (as class
helpers are implemented as child classes of the extended class this
might currently be possible)?

no

- should class helpers be able to implement interfaces?

This needs to be tested but I don't think they can. You can't define a helper that implements interface - so all interfaces should be listed in class. Another thing that you can reintroduce QueryInterface, GetInterface in the helper but I don't think they will be used by 'is' and 'as' operators.

- can/should "message" methods be forbidden?

In delphi they are not forbidden but also they can't be reached by Dispatch call.

- should abstract methods be forbidden?

In delphi they are not forbidden and require an implementation. It looks tht delphi skips 'abstract'. Also delphi skips 'virtual' and 'dynamic'. I think in FPC this should be forbidden.

- should a class helper for class X hide a method which was introduced
in a subclass of X?

no

- can class helpers extend generic classes?

no one example I tried was able to compile

I have attached few tests which answers to most of your questions.

Best regards,
Paul Ishenin
program tclasshelper1;

{$APPTYPE CONSOLE}

uses
  Messages;

type
  TFoo = class(TObject)
  strict private
    SP1: Integer;
  strict protected
    SP2: Integer;
  private
    P1: Integer;
  protected
    P2: Integer;
  public
    function Test: Integer;
    procedure VirtualMethod; virtual;
  end;

  TFoo1 = class(TFoo)
  public
    function Test: Integer;
  end;

  // test forward declaration
  // TFooHelper = class helper for TFoo; [DCC Error] tclasshelper1.dpr(17): 
E2029 'END' expected but ';' found

  TFooHelper = class helper for TFoo
  public
    function Test: Integer;
    procedure TestFieldsAccess;
    // procedure VirtualMethod; override; // [DCC Error] tclasshelper1.dpr(25): 
E2137 Method 'VirtualMethod' not found in base class
    procedure TestVirtual; virtual;
    procedure TestDynamic; dynamic;
    //procedure TestAbstract; virtual; abstract; // [DCC Error] 
tclasshelper1.dpr(28): E2065 Unsatisfied forward or external declaration: 
'TFooHelper.TestAbstract'
    procedure TestWM(var Message: TMessage); message WM_APP + 1;
    property PTest: Integer read Test;
  end;

  //TooHelper1 = class(TFooHelper) // [DCC Error] tclasshelper1.dpr(28): E2021 
Class type required
  //end;

  //TFooHelper1 = class helper for TFooHelper // [DCC Error] 
tclasshelper1.dpr(32): E2021 Class type required
  //end;

{ TFooHelper }

function TFooHelper.Test: Integer;
begin
  Result := 3;
end;

procedure TFooHelper.TestDynamic;
begin
  //
end;

procedure TFooHelper.TestFieldsAccess;
begin
  //SP1 := 1; // [DCC Error] tclasshelper1.dpr(26): E2003 Undeclared 
identifier: 'SP1'
  SP2 := 1;
  P1 := 1;
  P2 := 1;
end;

procedure TFooHelper.TestVirtual;
begin
  //
end;

procedure TFooHelper.TestWM(var Message: TMessage);
begin
  Message.Result := 1;
end;

{ TFoo }

function TFoo.Test: Integer;
begin
  Result := 1;
end;

procedure TFoo.VirtualMethod;
begin
  SP1 := 1;
end;

{ TFoo1 }

function TFoo1.Test: Integer;
begin
  Result := 2;
end;

var
  Foo: TFoo;
  Foo1: TFoo1;
  Message: TMessage;
begin
  Foo := TFoo.Create;
  Foo.TestFieldsAccess;
  if Foo.Test <> 3 then
    halt(1);

  Message.Msg := WM_APP + 1;
  Message.Result := 0;

  { message members can't be reached in class helpers }
  Foo.Dispatch(Message);
  if Message.Result <> 0 then
    halt(2);

  Foo.Free;
  Foo1 := TFoo1.Create;
  if Foo1.Test <> 2 then
    halt(3);
  Foo1.Free;
  WriteLn('ok');
end.
program tclasshelper2;

{$APPTYPE CONSOLE}
type
  TFoo<T> = class
  protected
    F: T;
  end;

  //TFooHelper = class helper for TFoo //[DCC Error] tclasshelper2.dpr(10): 
E2003 Undeclared identifier: 'TFoo'
  //end;

  //TFooHelper = class helper for TFoo<T> // [DCC Error] tclasshelper2.dpr(13): 
E2003 Undeclared identifier: 'T'
  //end;

  //TFooHelper = class helper for TFoo<Integer> // [DCC Error] 
tclasshelper2.dpr(17): E2086 Type 'TFoo<T>' is not yet completely defined
  //end;

begin
end.
_______________________________________________
fpc-devel maillist  -  [email protected]
http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply via email to