> On Dec 27, 2019, at 10:01 AM, Sven Barth via fpc-pascal 
> <fpc-pascal@lists.freepascal.org> wrote:
> 
> To be clear: with declaration time I mean when the type is written (" = class 
> ... end") versus creation time (either "var x: tmyclass" or "x := tmyclass 
> .create"). The difference would be that the user of the class would decide 
> what is supported instead of the declarer of the class. Adding something at 
> creation time would of course require that the functionality can only be 
> accessed dynamically (similar to GetInterface, though like that it can be 
> hidden behind e.g. the "as" operator) and that the functionality needs to be 
> independant of the existing class.

Got it.

> 
>> - Importing fields/properties is easy because we can just add symbols to the 
>> symbol table but I'm not sure what it means in terms of the compiler to 
>> import a method from another class. The method needs to be cloned or perhaps 
>> synthesized as I've seen the term used in the compiler.  Because the traits 
>> aren't actually allocated like a class or record we need to copy the code 
>> out into the class that uses them.
> 
> You don't need to do any copying of the functions. You need to partition the 
> instance so that fields that belong to a specific trait are grouped together 
> and then you pass an adjusted self pointer to the trait's methods so that 
> this only sees accesses its own fields (and properties are the same as 
> methods or field access: use the correct Self part).

Can you explain or gives some function names of where/how the importation of 
fields/methods happens for inheritance? For fields I'm seeing that the struct 
data size expands when a super class is parsed and then in searchsym_in_class 
the correct symbol is found but I don't know what happens after that. The data 
must be copied at some point but I don't know when.

For method calling I think you're saying we merely pass a different self 
pointer depending on which class in the hierarchy makes the call.

> 
> What I'm still missing however is a real use case. What you have presented as 
> an example can just as easily be done with the existing delegates. And just 
> to avoid having to cast the instance to the interface is in my opinion not 
> enough reason for a new feature.

It's really just about the namespace and avoiding deeply nested this.that.do 
kind of syntax. We could accomplish this using just plain records, no need to 
even get involved with the complicated interface syntax. According to the wiki 
https://en.wikipedia.org/wiki/Trait_(computer_programming) lots of other 
languages are having this need to build component like systems and want a 
syntax that formalizes the concept.

Adriaan, what was your idea you had in mind when you brought this up?

========================

program test;

type
  TBrain = record
    procedure Eat;
    procedure Fight;
  end;

type
  TPhysics = record
    x, y, z: float;
    procedure Apply;
  end;

type
  TPerson = class
    physics: TPhysics;
    brain: TBrain;
  end;

var
  p: TPerson;
begin
  p.brain.DoThis;
  p.physics.x += 1;
end.

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply via email to