FPC class syntax was extended to support delphi code

classic Classic list List threaded Threaded
18 messages Options
Reply | Threaded
Open this post in threaded view
|

FPC class syntax was extended to support delphi code

Paul Ishenin-2
Hello, FPC-Pascal users discussions

I want to notify you that fpc trunk has extensions for the class syntax.

Class can have now the next sections:

1. 'var' sections to start regular fields declaration. 'var' can be used
after other sections and after methods
2. 'class var' sections to start static fields declaration. Fields
delcared in the 'class var' section are static fields
3. 'type' sections to declare types local to a class. It is allowed now
to declare nested classes too.
4. 'const' section to declare constants local to a class.
5. 'class property' - similar to regular property but works with static
fields and methods

Some examples:
http://wiki.lazarus.freepascal.org/class_extensions_examples

Please test and report bugs found.

Best regards,
Paul Ishenin.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: FPC class syntax was extended to support delphi code

dmitry boyarintsev
Are these features available for {$mode delphi} only?

thanks,
dmitry
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: FPC class syntax was extended to support delphi code

David Emerson
In reply to this post by Paul Ishenin-2
Thank you for this message! This stuff sounds really cool. In
particular, I have been itching for class constants.

A few questions come to mind:

a. 'var' sections -- I assume that 'var' is optional when declaring
fields that occur first (i.e. directly after "private", "public", etc)

b. What does "strict private" mean, as opposed to private without
strict? (My best guess is that it would be accessible only within the
methods+properties of that class within the unit, as opposed to being
available anywhere in the same unit where the class is declared...???)

c. What is the purpose of a class method? It would seem to me that
methods should do the same thing whether they are class methods or not.
Traditional variables change from instance to instance, but methods do
not vary between instances, as far as I know-- right?

d. What happens with inheritance?

d.1. wrt class constants and class vars-- are there separate "instances"
(for lack of a better word) of these, one instance for each descendant?
Or is the class var/const only stored once for the ancestor that
declares it, and all descendants share that?

d.2. wrt class methods, can they be virtual? (This strikes me as being
closely related to d.1)

I guess an example is in order for d:

type
  t_parent = class
  private
    class var
      x : integer;
    const
      c = 5;
  end;

  t_child = class (t_parent)
  private
    const
      c = 7;  // can I do this?
  end;

If I change t_child.x will it change t_parent.x?

e. Is it available in {$mode objfpc}? (I hope I hope I hope)?

I'd love to test this stuff out, though I usually stick with release
versions... perhaps this is what is needed for me to take the plunge!
Either way, I'm looking forward to this being released. Great work.

Cheers,
David

On Wed 13 Jan 2010, Paul Ishenin wrote:
> Hello, FPC-Pascal users discussions
>
> I want to notify you that fpc trunk has extensions for the class
syntax.
>
> Class can have now the next sections:
>
> 1. 'var' sections to start regular fields declaration. 'var' can be
used
> after other sections and after methods
> 2. 'class var' sections to start static fields declaration. Fields
> delcared in the 'class var' section are static fields
> 3. 'type' sections to declare types local to a class. It is allowed
now
> to declare nested classes too.
> 4. 'const' section to declare constants local to a class.
> 5. 'class property' - similar to regular property but works with
static

> fields and methods
>
> Some examples:
> http://wiki.lazarus.freepascal.org/class_extensions_examples
>
> Please test and report bugs found.
>
> Best regards,
> Paul Ishenin.
> _______________________________________________
> fpc-pascal maillist  -  [hidden email]
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal
>



_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: FPC class syntax was extended to support delphi code

Doug Chamberlin
David Emerson wrote:
> b. What does "strict private" mean, as opposed to private without
> strict? (My best guess is that it would be accessible only within the
> methods+properties of that class within the unit, as opposed to being
> available anywhere in the same unit where the class is declared...???)

In Delphi what you have described is exactly what strict private gives you.

> c. What is the purpose of a class method? It would seem to me that
> methods should do the same thing whether they are class methods or not.
> Traditional variables change from instance to instance, but methods do
> not vary between instances, as far as I know-- right?

Class methods allow you to call the method without instantiating the
class first. For example, Result := TMyClass.MyClassFunction;

--
Doug C.
-----
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing in e-mail?
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: FPC class syntax was extended to support delphi code

David Emerson
Doug Chamberlin wrote:
> Class methods allow you to call the method without instantiating the
> class first. For example, Result := TMyClass.MyClassFunction;

Oh, that is so cool! I suppose that probably means that class methods
can only reference class variables/methods/properties.

Cheers,
David

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: FPC class syntax was extended to support delphi code

Doug Chamberlin
David Emerson wrote:
> Doug Chamberlin wrote:
>> Class methods allow you to call the method without instantiating the
>> class first. For example, Result := TMyClass.MyClassFunction;
>
> Oh, that is so cool! I suppose that probably means that class methods
> can only reference class variables/methods/properties.

Yup!

Of course, there are pros and cons to all this. Our once simple,
straightforward language is not littered with "convenience" features
that are not necessary at all. For example, what is the big advantage of
class methods over simple functions and procedures?

--
Doug C.
-----
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing in e-mail?
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: FPC class syntax was extended to support delphi code

Anthony Walter-3
Yup!

Of course, there are pros and cons to all this. Our once simple, straightforward language is not littered with "convenience" features that are not necessary at all. For example, what is the big advantage of class methods over simple functions and procedures?

Class methods can be virtual and have access to other (perhpas protected) class members of the class.

type
  TA = class
  public
    class procedure Hello; virtual;
  end;

  TB = class(TA)
  public
    class procedure Hello; override;
  end;

  TAClass = class of TA;

{ TA }

class procedure TA.Hello;
begin
  ShowMessage('Hello this is ' + ClassName); // see I can access ClassName
end;

{ TB }

class procedure TB.Hello;
begin
  inherited Hello;
  ShowMessage('A different message here');
end;

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var
  SomeClass: TAClass;
begin
  SomeClass := TB;
  SomeClass.Hello;
end;


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: FPC class syntax was extended to support delphi code

Aleksa Todorovic-2
In reply to this post by David Emerson
On Wed, Jan 13, 2010 at 19:13, David Emerson <[hidden email]> wrote:
>
> d.2. wrt class methods, can they be virtual? (This strikes me as being
> closely related to d.1)
>

Definitely, yes! (and I believe that was available before class
vars/consts) I use this great feature for (de)serialization of
messages in my client/server communication:

  TMessage = class
  public
    constructor Create; virtual;
    class function GetCode: Word; virtual;
    Code: Word;
    ...
  end;

constructor TMessage.Create;
begin
  Code := GetCode;
end;

So, when I want to create new message, I just call
TLoginMessage.Create or TChatMessage.Create or whatever (those classes
override GetCode, and everything works perfect).
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

RE: FPC class syntax was extended to support delphi code

Cox, Stuart TRAN:EX
In reply to this post by Doug Chamberlin
>-----Original Message-----

>From: [hidden email] [mailto:[hidden email]] On Behalf Of Doug Chamberlin
>Sent: Wednesday, January 13, 2010 11:21 AM
>To: FPC-Pascal users discussions
>Subject: Re: [fpc-pascal] FPC class syntax was extended to support delphi code
>
>David Emerson wrote:
>> Doug Chamberlin wrote:
>>> Class methods allow you to call the method without instantiating the
>>> class first. For example, Result := TMyClass.MyClassFunction;
>>
>> Oh, that is so cool! I suppose that probably means that class methods
>> can only reference class variables/methods/properties.
>
>Yup!
>
>Of course, there are pros and cons to all this. Our once simple,
>straightforward language is not littered with "convenience" features
>that are not necessary at all. For example, what is the big advantage of
>class methods over simple functions and procedures?
Some operations (procedures/functions) just go naturally with Classes but don't belong to any particular instance of that class.  
An example might be calculating the area of overlap between two geographic polygons (instances of the class) where the function returning the overlap area is a class function rather than an instance function/method of either of the two polygons.  Contrived, but imaginable.

>--
>Doug C.
>-----
>A: Because it messes up the order in which people normally read text.
>Q: Why is top-posting such a bad thing?
>A: Top-posting.
>Q: What is the most annoying thing in e-mail?
>_______________________________________________
>fpc-pascal maillist  -  [hidden email]
>http://lists.freepascal.org/mailman/listinfo/fpc-pascal

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: FPC class syntax was extended to support delphi code

Paul Ishenin-2
In reply to this post by dmitry boyarintsev
dmitry boyarintsev wrote:
> Are these features available for {$mode delphi} only?
>  
No. For objfpc too.

Best regards,
Paul Ishenin.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: FPC class syntax was extended to support delphi code

Doug Chamberlin
In reply to this post by Cox, Stuart TRAN:EX
Cox, Stuart TRAN:EX wrote:
> Some operations (procedures/functions) just go naturally with Classes but don't belong to any particular instance of that class.  
> An example might be calculating the area of overlap between two geographic polygons (instances of the class) where the function returning the overlap area is a class function rather than an instance function/method of either of the two polygons.  Contrived, but imaginable.

Oh, I can imagine such methods also. And I've used them before. I just
don't see the big advantage over having them be global
functions/procedures located in the same unit as the class they operate
on. So, as often as not, I go and create the global functions instead.
Never could decide either way to go.

--
Doug C.
-----
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing in e-mail?
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: FPC class syntax was extended to support delphi code

Paul Ishenin-2
In reply to this post by David Emerson
David Emerson wrote:
> a. 'var' sections -- I assume that 'var' is optional when declaring
> fields that occur first (i.e. directly after "private", "public", etc)
>  
Yes.
> b. What does "strict private" mean, as opposed to private without
> strict? (My best guess is that it would be accessible only within the
> methods+properties of that class within the unit, as opposed to being
> available anywhere in the same unit where the class is declared...???)
>  
"strict private" is not a new feature. it means that something is
private for this class only and can't be accessed by other classes or
routines of the unit.
> c. What is the purpose of a class method? It would seem to me that
> methods should do the same thing whether they are class methods or not.
> Traditional variables change from instance to instance, but methods do
> not vary between instances, as far as I know-- right?
>  
Class method is not a new feature as well as static class method. Class
method allows you to have methods which belongs to the class instead of
an instance of the class. Class methods can be virtual. Static class
methods can't.
> d. What happens with inheritance?
>
> d.1. wrt class constants and class vars-- are there separate "instances"
> (for lack of a better word) of these, one instance for each descendant?
> Or is the class var/const only stored once for the ancestor that
> declares it, and all descendants share that?
>  
Class vars (static class fields) are stored only once for the class
which declares them and all descendants share that.

Example:
TSomeClass = class
class var Value: Integer;
end;

TDescendant = class(TSomeClass);
begin
  TSomeClass.Value := 1;
  TDescendant.Value := 2;
  WriteLn(TSomeClass.Value); // this must output 2
end;

Class static field is not a new feature. But now you can declare them
using 'class var' section after methods or 'type'/'const' section.
> d.2. wrt class methods, can they be virtual? (This strikes me as being
> closely related to d.1)
>  
class methods can be virtual. static class methods can't.

> I guess an example is in order for d:
>
> type
>   t_parent = class
>   private
>     class var
>       x : integer;
>     const
>       c = 5;
>   end;
>
>   t_child = class (t_parent)
>   private
>     const
>       c = 7;  // can I do this?
>   end;
>  
In ObjFpc mode you can't do this because t_child.c duplicates
t_parent.c. In Delphi mode you can do this. I have no personal opinion
how ObjFpc mode should work here but this behavior is consistent with
restrictions for identifier duplication we currently have in objfpc mode.
> e. Is it available in {$mode objfpc}? (I hope I hope I hope)?
>  
yes.

Best regards,
Paul Ishenin.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: FPC class syntax was extended to support delphi code

Andreas Schneider-7
In reply to this post by Doug Chamberlin
I think they come in very handy for the Singleton OOP concept. You need to
have a "factory" that handles the object query/instantiation. If no instance
is available, it creates a new one (and stores it) and if one is already
available, it just returns that.
Naturally that looks better to have TSomeClass.GetInstance() instead of
GetInstanceOfSomeClass() ...
Sure, it's possible to do without class methods, but from an OOP viewpoint it
just looks and feels wrong ;-) (imho)


Am Donnerstag 14 Januar 2010 01:50:02 schrieb Doug Chamberlin:
> Oh, I can imagine such methods also. And I've used them before. I just
> don't see the big advantage over having them be global
> functions/procedures located in the same unit as the class they operate
> on. So, as often as not, I go and create the global functions instead.
> Never could decide either way to go.
>
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: FPC class syntax was extended to support delphi code

Marc Weustink
In reply to this post by Paul Ishenin-2
Paul Ishenin wrote:

> David Emerson wrote:
>> d. What happens with inheritance?
>>
>> d.1. wrt class constants and class vars-- are there separate
>> "instances" (for lack of a better word) of these, one instance for
>> each descendant? Or is the class var/const only stored once for the
>> ancestor that declares it, and all descendants share that?
>>  
> Class vars (static class fields) are stored only once for the class
> which declares them and all descendants share that.
>
> Example:
> TSomeClass = class
> class var Value: Integer;
> end;
>
> TDescendant = class(TSomeClass);
> begin
>  TSomeClass.Value := 1;
>  TDescendant.Value := 2;
>  WriteLn(TSomeClass.Value); // this must output 2
> end;
>
> Class static field is not a new feature. But now you can declare them
> using 'class var' section after methods or 'type'/'const' section.

Can we have a virtual version too like described here
http://hallvards.blogspot.com/2007/05/hack17-virtual-class-variables-part-i.html


Marc

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: FPC class syntax was extended to support delphi code

Paul Ishenin-2
Marc Weustink wrote:
> Can we have a virtual version too like described here
> http://hallvards.blogspot.com/2007/05/hack17-virtual-class-variables-part-i.html 
>
Well, I suppose we can if someone will implement ;)

Best regards,
Paul Ishenin.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: FPC class syntax was extended to support delphi code

Arioch1
This post has NOT been accepted by the mailing list yet.
In reply to this post by Andreas Schneider-7
Can FPC have default class properties in Delphi mode or even ObjFpc mode?

Andreas Schneider-7 wrote
I think they come in very handy for the Singleton OOP concept. You need to
have a "factory" that handles the object query/instantiation. If no instance
is available, it creates a new one (and stores it) and if one is already
available, it just returns that.
Naturally that looks better to have TSomeClass.GetInstance() instead of
GetInstanceOfSomeClass() ...
Sure, it's possible to do without class methods, but from an OOP viewpoint it
just looks and feels wrong ;-) (imho)
Reply | Threaded
Open this post in threaded view
|

Re: FPC class syntax was extended to support delphi code

Arioch1
In reply to this post by Andreas Schneider-7
В письме от Thu, 14 Jan 2010 18:50:50 +0400, Andreas Schneider  
<[hidden email]> сообщал:

Can FPC have default class properties in Delphi mode or even ObjFpc mode?


i probably won't really do it, for my major concern is still Delphi, and  
that makes a special note that "defaul" and "class" are mutually exclusive.

  Pity... i wished to do a light-weight factory (which Delphi class  
references are to an extent). I would have to resort to global procedure,  
but that is less elegant.
  And calling TClassName.a(DataPayload) is awful. TClassName[DataPayload]  
would be neat...

> I think they come in very handy for the Singleton OOP concept. You need  
> to
> have a "factory" that handles the object query/instantiation. If no  
> instance
> is available, it creates a new one (and stores it) and if one is already
> available, it just returns that.
> Naturally that looks better to have TSomeClass.GetInstance() instead of
> GetInstanceOfSomeClass() ...
> Sure, it's possible to do without class methods, but from an OOP  
> viewpoint it
> just looks and feels wrong ;-) (imho)



--
Написано в почтовом клиенте браузера Opera: http://www.opera.com/mail/

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: FPC class syntax was extended to support delphi code

Arioch1
In reply to this post by Arioch1
To draw a perspective, i am coming from, i want to use a library, that is built with long procedures, having 5-10 parametes, of those i usually really only need to set one or two.

 So i naturally decided to make a wrapper with fluent-style, chained API, so i can only set those params that i actually need customized. But Fluent API requires automatic lifetime management, which in Delphi means using ref-counted interfaces.

 And that comes with a problem - constructor return an object, not an interface.
 And even i make all the methods on object go protected and on;y exposed via interface, i have doubts that all the compilers would successfully implicitly typecast it. Most probably they would not. And doing manual typecast damages clean and simple ease of use for Fluent-style API.

 Maybe you know about Jedi CodeLib library. It supports FPC 2.4 and recently unofficial patchset for 2.6 was released.
 It has a TJclStringList/IJclStringList extenstion of a stock class.

 Recently on stackoverflow there came yet another question that in effect was reduced "how to read all the lines from text file and split them on some delimeter.

 My usual answer for this goes along the lines
var s: string; isl1, isl2: IJclStringList;
...
isl1 := TJclStringList.Create; isl1.LoadFromFile(...);
...
for s in isl1 do begin
   isl2.Split(s, delimeter-char).Trim.Add(['some string', 'some another string']).UpperCase. ...;
   // refining of strings can be chained

    // iterating through refined split data in isl2
end;

 This time i was in a haste and drafted like
isl1 := TJclStringList.Create.LoadFromFile(...);

 Well, actually that most probably would not even compile, but if it would - it would be a memory leak, because between constructor and LoadFrom*** call - there is no interface reference yet, but a PODO reference.

 This obvious error, but is so easy to make when u want to type fast and fluentized.
 So that gave me another reason to try to side-step Delphi object constructor.
 But then how would i call factory-method? some simple name like "a", "b", "c,", "_" - would have no sense an d look ugly and hard to remember. Some lone name would harm conciseness of fluent style and would be against OOP "object.verb" style. It would be like making method TStringList.LoadStringListFromFile - DRY principle is good even in naming

 Then i got a flash and devised to outsmart Delphi with a construct like this:
type
  TData = class end;  // some object we need to operate upon
  IDataHandler = interface end; //some methods to make Fluent-Style, daisy-chain API

  { TDataExporter }

  TDataExporter = class(IDataHandler, TInterfacedObject)
     protected
        Payload: TData;
        constructor CreateFor(const d: TData);
        class function    MakeNewExporter(const d: TData): IDataHandler; static;

        /// all other functions, setting this or that parameter and
        /// returning Self as IDataHandler

     public
        procedure AfterConstruction; override;

        class property Factory[Payload: TData]: IDataHandler read MakeNewExporter; default;
  end;                          


{ TDataExporter }

class function TDataExporter.MakeNewExporter(const d: TData): IDataExporter;
begin
  Result := TDataExporter.CreateFor(d);
end;

procedure TDataExporter.AfterConstruction;
begin
  if Self.Payload = nil then raise Exception.Create('You should not create via inherited TObject.Create!');
end;

constructor TDataExporter.CreateFor(const d: TData);
begin
  if d = nil then raise Exception.Create('Payload data is required!');
  Self.Payload := d;
end;                    

 And you know what... dunno if it works or not, but at least it compiled in CT 3.10 Win64


var i: IDataHandler;
begin
  i := TDataExporter[TData.Create];
end;

procedure TForm1.FormCreate(Sender: TObject);
var i: IDataHandler;  d: TData;
begin
  d := TData.Create;
  i := TDataExporter[d];
end;    

unit1.pas(52,22) Error: Illegal qualifier

 in both Delphi and ObjFpc mode  :-(((




Arioch1 wrote
Can FPC have default class properties in Delphi mode or even ObjFpc mode?

Andreas Schneider-7 wrote
I think they come in very handy for the Singleton OOP concept. You need to
have a "factory" that handles the object query/instantiation. If no instance
is available, it creates a new one (and stores it) and if one is already
available, it just returns that.
Naturally that looks better to have TSomeClass.GetInstance() instead of
GetInstanceOfSomeClass() ...
Sure, it's possible to do without class methods, but from an OOP viewpoint it
just looks and feels wrong ;-) (imho)