Jump to content

Koru

Members
  • Content Count

    20
  • Joined

  • Last visited

Posts posted by Koru


  1. It always happens with the same elements of the same form or is it something random along the whole application?

    Faced with strange problems of the visual part, I would also check that there is no thread that touches visual things without the correct synchronization

     


  2. I would look for all the pieces of code that can cause that behavior or touch those components in some way, and leave a log when they are executed making it clear in the log what part of the code has been executed. In the log I would place also information about the new state of the components: position, visible, enabled,...


  3. 10 hours ago, Stefan Glienke said:

    Yeah sure... Good luck with that - there are tons of more frequently asked and easier to design and implement features open for years.

    I am very certain that Bruneau had the C++ approach in his mind even though he mentioned .NET/Java (which have GC that Delphi does not have) because otherwise memory management would clash.

     

    And if I am not totally mistaken after a bit of search you cannot even implement more than one interface per class in C++ - but again my practical C++ experience is many years ago.

     

    Now C# and Java can implement multiple interfaces per class and under the hood interfaces are basically the same as classes just that you cannot instantiate them. But the compiler and the runtime know about all that - if you think Embarcadero can pull this off you must be new to the game.

    Unfortunately we are nothing new with Delphi, although we may seem so, but with a halo of hope.
    Ok, the opinions are clear, we continue with the fight on our own. Thank you very much to all


  4. 2 hours ago, Stefan Glienke said:

    There is no proposal - there is just a "it would be cool if" without any actual suggestions how something can be achieved.

    I asked a couple of questions but they have not been answered (or I missed those) that are important to decide if something like event<->interface method binding can be achieved and how it would look like.

    Currently any assignment of interface methods to an event would break reference counting similar to how anonymous methods can't be assigned to an event. One is a managed type, the other is a record with 2 raw pointers.

     

    Now we could all list stuff that would be cool to have without actually evaluating if that is technically possible - but to me that would be just a waste of time I could spend more productive.

    Yes, we are asking for a wish list, without knowing the technical details. The context is 'Embarcadero says they can do it', and we look for ideas that come from people who have stuck with current interfaces, know the limitations they have and would like to solve. All this knowing that then Embarcadero will probably do it his way. But who knows ... maybe they'll hear us on something. And that was the idea.

     

    I am sorry that we do not know how to help you more in the technical section, because we only wanted to move in the ideas leaving aside how it is done. In another post Javier says 'there is already an embarcadero answer on Quality portal, acknowledging this is feasable, and would work as expected'...reason why we believe that the technical aspect is solved already by Embarcadero, but any doubt that there is in this regard can also be presented to Embarcadero for clarification if possible, with specific questions.

     

    So I understand what you ask Stefan, and maybe there is some detail in the comments of the link at the end that clarifies you something, or even you can ask any doubt there directly (they are answering all our questions so far): https://quality.embarcadero.com/browse/RSP-27911


  5. 3 minutes ago, Stefan Glienke said:

    You are avoiding to answer the important question that is the reason why this does not work with COM interfaces.

    Methods (including interface methods) and method pointers are different language elements and they are not compatible. Technically, a method pointer is a TMethod element (Code+Data).

    We are talking again about the particular way it has been implemented
    Just for a moment, forget the implementation, and look at the question from the programmer perspective
    Why should not be able to use an interface method as an event method? Behind every and each interface there is an object


  6. 58 minutes ago, Stefan Glienke said:

    My thoughts:

    2. modify QueryInterface to take care of looking through the implemented interfaces if any of them inherits from the requested if it was not implemented implicitly - or simply add base interfaces to the implementing class - not a big deal fwiw.

    3. what exactly does that mean?

    4. reference counting issue - a procedure of object is just two raw pointers - how does that mix with interfaces - now if those COM-free interfaces would not have reference counting implemented the problem I described previously arises which will make them rather pointless.

    The usage of the native interfaces must be more or less the same as the com based, I mean the declaration should be more or less equal maybe with some new reserved word, and the implementation in a class should be similar also.

    A silly example could be:

     IMyTest= nativeinterface
       ['{16E3EB88-4654-495A-9699-AC9FA2612352}']
       procedure DoProc;
       function DoFunc: Boolean;
     end;
    
     TMyTest = class(TNativeInterfacedObject, IMyTest)
     public
       procedure DoProc;
       function DoFunc: Boolean;
     end;

    With actual interfaces you can't do next (Button2Click will fail at compile time):

    type
     TProcTest = procedure of object;
     TFuncTest = function : Boolean of object;
    
     IMyTest= interface
       ['{16E3EB88-4654-495A-9699-AC9FA2612352}']
       procedure DoProc;
       function DoFunc: Boolean;
     end;
    
     TMyTest = class(TInterfacedObject, IMyTest)
     public
       procedure DoProc;
       function DoFunc: Boolean;
     end;
    
     TExecutor = class
       public
         procedure ExecuteIfCheckIsTrue(const AExec: TProcTest; const ACheck: TFuncTest);
     end;
    
      TForm67 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    
    var
      Form67: TForm67;
    
    implementation
    
    {$R *.dfm}
    
    { TMyTest }
    
    function TMyTest.DoFunc: Boolean;
    begin
      Result := True;
    end;
    
    procedure TMyTest.DoProc;
    begin
      ShowMessage('Hi!');
    end;
    
    { TExecutor }
    
    procedure TExecutor.ExecuteIfCheckIsTrue(const AExec: TProcTest;
      const ACheck: TFuncTest);
    begin
      if ACheck() then
        AExec();
    end;
    
    procedure TForm67.Button1Click(Sender: TObject);
    var
      L1: TMyTest;
      L2: TExecutor;
    begin
      L1 := TMyTest.Create;
      L2 := TExecutor.Create;
      L2.ExecuteIfCheckIsTrue(L1.DoProc, L1.DoFunc);
    end;
    
    procedure TForm67.Button2Click(Sender: TObject);
    var
      L1: IMyTest;
      L2: TExecutor;
    begin
      L1 := TMyTest.Create;
      L2 := TExecutor.Create;
      L2.ExecuteIfCheckIsTrue(L1.DoProc, L1.DoFunc);  //this statement doesn't compile
    end;

    But this should be possible with the native interface.

    Things like this, from the developer point of view looks like it should work (at least from my point of view :classic_smile:), we should not know that the interface comes from COM and all that history...so you can't do this and this an this...but...you can do all that things with the class that implements that interface. If you don't know the internals of the issue it's weird, and a little bit inconsistent...

    There are probably considerations that those of us who are not experts miss along the way, but the usefulness seems clear


  7. 8 minutes ago, Stefan Glienke said:

    "Native Interface" is a terrible name tbh - what exactly would be "native" about it that current interfaces are not.

     

    A look at other languages might be helpful to actually define clearly what your desired requirements are - for example traits in Scala.

    Putting proper names always leads to headaches  :classic_smile:

    And it is relevant, but it is not the goal of the post. The goal is to know what deficiencies or limitations we see to the current interfaces in Delphi, partly (or mostly) because they were born from COM.

    By native interface we have been calling in the post to that interface that we know that behind it has a Delphi class, and under that assumption I would like things like the ones I list in the first post, that probably would be enough advance for me: 'As an example, you can't use an interface method as an event handler. You can't use anything that expects a "procedure of object" or "function of object", nor use generics or other modern features'
    But I know that there are people like you who that have struggled a lot with the interfaces and I'm sure you have clearer limitations that perhaps I can't see.

     

     


  8. 6 minutes ago, Anders Melander said:

    But it isn't true. The IFooBar interface inherits the methods of IBar - at compile time. The implementing object doesn't inherit the contract that it must implement the IBar interface.

     

    I'm not convinced that John Kaster knew what he was talking about when he wrote that. I mostly included the link because it seems to be the earliest mention of the feature.

    The limitation as-is matches my recollection of "the rules of COM" but I could be mistaken. I'm not up to reading the COM bible again just to find out. It was hard enough the first time(s). :classic_smile:

    I have the feeling that we are talking about how it works now (you correct me if I'm wrong), not how we would like it to work, and I talk about how I would like it to work.

    In this specific case if the native interfaces have inheritance capacity, these possibilities would be viable, if they are clearly useful for the developers of course


  9. 12 minutes ago, Stefan Glienke said:
    17 minutes ago, Stefan Glienke said:

    There is nothing logical about it - as the previously linked article says:

     

    Hi,

    not having an extensive knowledge of the subject can lead me to erroneous statements, if so, do not hesitate to correct me. If we talk about a new implementation of the interfaces as native interfaces, no longer tied to COM, I understand that Embarcadero can make those limitations cease to exist, is what I say correct or is there something I am leaving out?

     


  10. 3 hours ago, Uwe Raabe said:

    If I am not mistaken, Koru is referring to a different case:

    
    type
      IBar = interface
        ['{570FBD40-8ECF-4B4B-9898-EF3F4146FFF9}']
      end;
    
      IFooBar = interface(IBar)
        ['{1A99C9D3-CC94-4BCE-BF9C-354BF14EC5C7}']
      end;
    
    type
      TFooBar = class(TInterfacedObject, IFooBar)
      end;
    
    procedure Test;
    begin
      var
      FooBarObject := TFooBar.Create;
    
      Assert(Supports(FooBarObject, IFooBar));
      Assert(Supports(FooBarObject, IBar));  //Fails!
    end;

    For me this is pretty logical, so nothing to be changed.

    Hi again, why do you see it logical? I think it seems quite illogical to ask that to this function and to answer that it's false when we know it's true


  11. 12 minutes ago, Uwe Raabe said:

    If I am not mistaken, Koru is referring to a different case:

    
    type
      IBar = interface
        ['{570FBD40-8ECF-4B4B-9898-EF3F4146FFF9}']
      end;
    
      IFooBar = interface(IBar)
        ['{1A99C9D3-CC94-4BCE-BF9C-354BF14EC5C7}']
      end;
    
    type
      TFooBar = class(TInterfacedObject, IFooBar)
      end;
    
    procedure Test;
    begin
      var
      FooBarObject := TFooBar.Create;
    
      Assert(Supports(FooBarObject, IFooBar));
      Assert(Supports(FooBarObject, IBar));  //Fails!
    end;

    For me this is pretty logical, so nothing to be changed.

    Hi, yes I was referring to something like this case you point.

    Well, it may be that the approach was not very correct. My idea focused on a context where we can ask native interfaces for information similar to what we can ask to classes, such as for example: if it inherits from a certain base interface. And in that context I was handling the idea (perhaps wrong, we are talking about ideas and giving possibilities) that the Supports function was capable of giving that functionality


  12. Speaking about possible new features, it's a mess that the Supports function doesn't see any of the base interfaces of a possible inheriteance tree. Only the interfaces that are declared in the class header are visible to this function, so you are forced to write the interfaces in the header, as you see you need them here or there. So it would be nice that this kind of functions can work with base interfaces


  13. 2 hours ago, Kas Ob. said:

    Brain storming, huh.....  i have some still working.

     

    How about reverse interface declaration, i mean let the compiler build base interfaces from classes

    Like this

    
    type
      TProcessor = class
      public
        constructor Create;
        procedure ProcessData(var Data); IMethod;   // IMethod will only be used when InterfaceOf is declared
        procedure CleanUp; IMethod;
      end;
    
      IProcessor = InterfaceOf(TProcessor);
    
      // IProcessor with the above one line declaration is identical to the following
      {
      IProcessor = interface
        procedure ProcessData(var Data);
        procedure CleanUp;
      end;
      }
    
      // and can be extended like this
      IPostProcessor = InterfaceOf(TProcessor)
        procedure NotifyFinish;
      end;
    
      // or like this
      TCompressor = class
      public
        procedure Compress; abstract; IMethod;
      end;
    
      IDataCompressor = Interface(InterfaceOf(TProcessor), IInterface, InterfaceOf(TCompressor));

     

    Hi, thank you very much for your proposals!

    I talk about personal tastes, but I prefer to see at a glance the definition of the interface (contract), for me it's more difficult the way you present the new interface since you have to extract it mentally from different parts of the source code

     


  14. Interface-oriented development is an awesome tool, and the ARC memory management that usually comes with it can be great as well.

     

    But in our beloved Delphi, interfaces are not full citizens.


    Working with Delphi interfaces becomes soon troublesome; the way they have been implemented makes impossible some of the common stuff we do in our daily programming


    As an example, you can't use an interface method as an event handler. You can't use anything that expects a "procedure of object" or "function of object", nor use generics or other modern features.


    Why? Because the interfaces we have in Delphi were introduced just and only to achieve COM integration. So, the interfaces don't know they always have an object (delphi class) behind them 


    So we need a remake of Delphi interfaces, but we can't break the software already using them


    Here comes the "native interface": probably they should have a distinction on their declaration, so the compiler knows to handle them


    And the big difference using them, is that native interface methods are object methods, so the compiler would know how to handle them.


    I would like this post to serve as brainstorming for those of you who have ideas about how to enable this division of the com-based interface and a possible new native implementation, implementation of which there may also be proposals for improvement.


    For example, at least for me, it would be nice if interfaces (at least the native ones) could have multiple inheritance of interfaces:

      InterfaceTest = ninterface(Interface1, Interface2, Interface3)
        procedure Test;
      end;

    Feel free to comment in any direction.

    • Like 2
×