Results 1 to 23 of 23

Thread: Confusion about Interfaces

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2022
    Posts
    334

    Confusion about Interfaces

    Hi all.

    I have a couple of questions regarding Interfaces.

    1- Say we have two classes that both implement a common interface. For example:

    StdPicture Class implements IPersistStream
    Stream Class implements IPersistStream

    My understanding is that, in theory, each implementation of IPersistStream need not be the same. ie: StdPicture and Stream classes should have the liberty to execute diff codes for any given IPersistStream function.

    But in practice, that's not what I see. It wouldn't make sense for each Class to execute a diff code for a common interface function. It would yield chaotic and unexpected results.

    2- Another thing I am confused about is that an Interface contains only the skeleton definitions of functions and no code as opposed to implementations of the interface. However, I see that some Interfaces implement other interfaces meaning they do contain code (implementation code of the other interface(s)) not just function signatures.

    Thanks.
    Last edited by AngelV; Apr 17th, 2024 at 01:47 AM.

  2. #2
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    7,060

    Re: Confusion about Interfaces

    1) That mess is part of why VB6/VBA don't allow you to use Implements on interfaces that inherit from anything besides IDispatch or IUnknown, and it handles those two under the hood. In twinBASIC (and obviously C/C++), you can, but you have control over whether you write separate or common implementations, and you're right, you *should* use a common one, but don't *have to*.

    2) I'm not sure what you mean here; interfaces don't implement other interfaces. They can inherit from them, but that just means the function pointers of the inherited interface precede its own in the vtable.
    Last edited by fafalone; Apr 17th, 2024 at 02:16 AM.

  3. #3
    PowerPoster Zvoni's Avatar
    Join Date
    Sep 2012
    Location
    To the moon and then left
    Posts
    5,035

    Re: Confusion about Interfaces

    @1
    On the Contrary: I'd expect different behaviour
    You define an Interface "IAnimal" which provides a Skeleton-Procedure "Move"

    You define three classes "Dog", "Snake" and "Fish" which each implement IAnimal.
    You write the different code for each "Move"-Procedure for your 3 classes

    Now if you pass one of the 3 "Classes" to a Function which expects an IAnimal-Object as an Argument, that Procedure will automatically know WHICH code to execute
    Code:
    Public Function SomeFunction(ByRef SomeAnimal As IAnimal) As SomeType
       SomeAnimal.Move
    End Function
    @2
    If you have a "Chain" of Interfaces, any code contained within is ignored by the implementing object

    But might be wrong, but that's my understanding of it
    Last edited by Zvoni; Tomorrow at 31:69 PM.
    ----------------------------------------------------------------------------------------

    One System to rule them all, One Code to find them,
    One IDE to bring them all, and to the Framework bind them,
    in the Land of Redmond, where the Windows lie
    ---------------------------------------------------------------------------------
    People call me crazy because i'm jumping out of perfectly fine airplanes.
    ---------------------------------------------------------------------------------
    Code is like a joke: If you have to explain it, it's bad

  4. #4

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2022
    Posts
    334

    Re: Confusion about Interfaces

    @fafalone:
    Stdole.IPicture inherits from IUnknown but still, the following doesn't seem to work !

    Code:
    Implements stdole.IPicture
    The above line when added to a class module compiles ok but the IDE doesn't show any of the IPicture Properties or Methods implementation handlers as one would expect. I wonder why that is.

    I'm not sure what you mean here; interfaces don't implement other interfaces. They can inherit from them, but that just means the function prototypes of the inherited interface precede its own in the vtable
    Yep. That's what I meant to say. Makes sense.

  5. #5

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2022
    Posts
    334

    Re: Confusion about Interfaces

    @Zvoni
    On the Contrary: I'd expect different behaviour
    Makes perfect sense with custom made interfaces but I still don't see how that would make sense with interfaces such as the one I mentioned (IPersistStream) when diff client classes such as Stream and StdPicture want to implement any of the IPersistStream Properties & Methods.

    If you have a "Chain" of Interfaces, any code contained within is ignored by the implementing object.
    But might be wrong, but that's my understanding of it
    I think fafalone answered that.one.

  6. #6
    Fanatic Member
    Join Date
    Jan 2013
    Posts
    807

    Re: Confusion about Interfaces

    Quote Originally Posted by AngelV View Post
    I still don't see how that would make sense with interfaces such as the one I mentioned (IPersistStream) when diff client classes such as Stream and StdPicture want to implement any of the IPersistStream Properties & Methods.
    The difference is what each class does internally when the Interface method is called.
    Take an StdPicture object that implements IPersistStream.
    You can call the Save() method on it and the StdPicture object "saves" itself down the stream.

    Question: What Data passes down that stream?
    Answer: Whatever data the StdPicture needs to send to persist itself.

    Same with the Load() method.
    What Data will the StdPicture object expect to pull from the stream? Again, whatever it needs to populate itself.

    Regards, Phill W.

  7. #7
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,895

    Re: Confusion about Interfaces

    Quote Originally Posted by AngelV View Post
    My understanding is that, in theory, each implementation of IPersistStream need not be the same. ie: StdPicture and Stream classes should have the liberty to execute diff codes for any given IPersistStream function.

    But in practice, that's not what I see. It wouldn't make sense for each Class to execute a diff code for a common interface function. It would yield chaotic and unexpected results.
    WAT? Of course the code is different with each implementation of IPersistStream.

    This is like having Move method on a Form, FlexGrid and Image control and insisting that the code executed on Move is the same in all 3 objects.

    Now, every form executes the same code on Move. When you move two Image controls it is the same Move method (the same code) which gets executed on both of them. But Move on form and Move on Image control execute different code.

    cheers,
    </wqw>

  8. #8
    PowerPoster Zvoni's Avatar
    Join Date
    Sep 2012
    Location
    To the moon and then left
    Posts
    5,035

    Re: Confusion about Interfaces

    Quote Originally Posted by wqweto View Post
    WAT? Of course the code is different with each implementation of IPersistStream.

    This is like having Move method on a Form, FlexGrid and Image control and insisting that the code executed on Move is the same in all 3 objects.

    Now, every form executes the same code on Move. When you move two Image controls it is the same Move method (the same code) which gets executed on both of them. But Move on form and Move on Image control execute different code.

    cheers,
    </wqw>
    I'll add to this, since i come from Lazarus/Freepascal:
    Lazarus/FreePascal has your usual Controls you can place on a Form (TButton, TEdit, TLabel etc.), and they all inherit from a common "ancestor"-Interface, getting their Methods, e.g. the "Paint"-Method

    BUT: In Lazarus you write code on a Windows-Machine, but then you decide to compile for Linux-GTK2 (or QT).
    You don't have to change a single line in YOUR code, but in the background the Interface calls the correct method for the correct OS

    This is just an example of why it's perfectly legal, that a common interface provides the possibility to execute different code
    Last edited by Zvoni; Tomorrow at 31:69 PM.
    ----------------------------------------------------------------------------------------

    One System to rule them all, One Code to find them,
    One IDE to bring them all, and to the Framework bind them,
    in the Land of Redmond, where the Windows lie
    ---------------------------------------------------------------------------------
    People call me crazy because i'm jumping out of perfectly fine airplanes.
    ---------------------------------------------------------------------------------
    Code is like a joke: If you have to explain it, it's bad

  9. #9

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2022
    Posts
    334

    Re: Confusion about Interfaces

    Thanks guys. I am happy that I have now this confirmed. Each implementing class executes *similar* but diff code under the hoods. (which is in fact, the whole point for bothering to have interfaces)

    One more related question:

    Why Implements stdole.IPicture added to a class module doesn't work like when implementing my own interfaces defined in my vbproject? Same with other interfaces from other referenced libraries.

  10. #10
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,895

    Re: Confusion about Interfaces

    Quote Originally Posted by AngelV View Post
    Why Implements stdole.IPicture added to a class module doesn't work like when implementing my own interfaces defined in my vbproject? Same with other interfaces from other referenced libraries.
    Limitation of VBx -- it needs implemented interface to derive from IDispatch because VBx can produce dual-interfaces only (i.e. IDispatch based ones) and cannot produce non-dual interface (i.e. not derived from IDispatch) as would be the case if it allowed IPicture to be implemented.

    VBx needs all it's classes to be "castable" to Object data-time (an IDispatch in disguise) so that Dim o As Object variable can hold a reference to an instance of any VBx class.

    Btw, TwinBasic can implement stdole.IPicture (and stdole.IPictureDisp)

    cheers,
    </wqw>

  11. #11
    PowerPoster Zvoni's Avatar
    Join Date
    Sep 2012
    Location
    To the moon and then left
    Posts
    5,035

    Re: Confusion about Interfaces

    Quote Originally Posted by AngelV View Post
    Thanks guys. I am happy that I have now this confirmed. Each implementing class executes *similar* but diff code under the hoods. (which is in fact, the whole point for bothering to have interfaces)

    One more related question:

    Why Implements stdole.IPicture added to a class module doesn't work like when implementing my own interfaces defined in my vbproject? Same with other interfaces from other referenced libraries.
    Because there is no IPicture-Interface?
    https://learn.microsoft.com/en-us/do...dole.ifontdisp
    Last edited by Zvoni; Tomorrow at 31:69 PM.
    ----------------------------------------------------------------------------------------

    One System to rule them all, One Code to find them,
    One IDE to bring them all, and to the Framework bind them,
    in the Land of Redmond, where the Windows lie
    ---------------------------------------------------------------------------------
    People call me crazy because i'm jumping out of perfectly fine airplanes.
    ---------------------------------------------------------------------------------
    Code is like a joke: If you have to explain it, it's bad

  12. #12
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    7,060

    Re: Confusion about Interfaces

    There is an IPicture interface but it's hidden and like the other interfaces in stdole2.tlb, VB6 restricts what you can do with it.

    Here it wouldn't matter anyway-- the default definition of IPicture includes a method with an As Any argument and out-only arguents, which are unsupported by VB6 so you couldn't implement the interface as-is anyway. You'd need to make a typelib with a unrestricted, VB friendly version, like oleexp does with IUnknown and IDispatch..

  13. #13
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,895

    Re: Confusion about Interfaces

    Yes, having As Any parameters would be the true root cause.

    There is no problem implementing IUnknown derived interfaces, just tested with oleexp.IContextMenu.

    Casting such VBx implemented IContextMenu to Object succeeds because the default interface is always IDispatch derived so you get IDispatch on the default interface instead.

    cheers,
    </wqw>

  14. #14

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2022
    Posts
    334

    Re: Confusion about Interfaces

    The Default Interface for the StdPicture CoClass is the IPicture interface so in theory, StdPicture should have the same members as IPicture. However, that doesn't seem to be the case as shown in the next two screenshots:

    What am i missing here?

    Attachment 191178

    Name:  Untit222222led.png
Views: 200
Size:  10.2 KB
    Attached Images Attached Images  
    Last edited by AngelV; Apr 17th, 2024 at 07:35 AM.

  15. #15
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,895

    Re: Confusion about Interfaces

    How do you inspect default interface on a coclass with Object Viewer?

    Here is a snippet from OLE View decompiled stdole2.tlb

    Code:
        typedef [public] Picture IPictureDisp;
    
        [
          uuid(0BE35204-8F91-11CE-9DE3-00AA004BB851)
        ]
        coclass StdPicture {
            [default] dispinterface Picture;
            interface IPicture;
        };
    The default interface is actually Picture dispinterface. It is a dispinterface so all calls on StdPictures in VBx are late-bound.

    In addition IPictureDisp turns out is a typedef (alias) of this Picture dispinterface.

    cheers,
    </wqw>

  16. #16

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2022
    Posts
    334

    Re: Confusion about Interfaces

    @wqweto
    How do you inspect default interface on a coclass with Object Viewer?
    No. I used TypeLib Browser by Jose Roca.

    I now see I made a mistake as the default interface is not IPicture 78F80981 VS 78F80980 and I didn't see either where it clearly says at the bottom Picture (default interface) (See image attachements below)


    It is a dispinterface so all calls on StdPictures in VBx are late-bound.
    I see.
    Is that the reason why both codes below work whether we use the New keyword or not ?
    Code:
    Dim oStdPic As New StdPicture
    Set oStdPic = LoadPicture( ....
    Code:
    Dim oStdPic As StdPicture
    Set oStdPic = LoadPicture( ....
    Attached Images Attached Images   

  17. #17
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,895

    Re: Confusion about Interfaces

    Yes, As New declarations can happen with coclasses only (i.e. cannot use interface names).

    For instance these 3 are equivalent:

    Code:
        Dim oStdPic As StdPicture
        Set oStdPic = LoadPicture()
        Debug.Print oStdPic.Handle
        
        Dim oStdPic2 As Picture
        Set oStdPic2 = LoadPicture()
        Debug.Print oStdPic2.Handle
        
        Dim oStdPic3 As IPictureDisp
        Set oStdPic3 = LoadPicture()
        Debug.Print oStdPic3.Handle
    i.e. the 3 refs have the same properties/methods *but* only StdPicture is a coclass and can be used with As New.

    The rule is simple: Dim with interface, New with coclass.

    When you Dim with coclass (which everyone usually does) the compiler substitutes the coclass for its default interface.

    As New "shortcut" syntax is the weird one as it has to both Dim and New so it's only possible with coclass which Dims with its default interface.

    As New is frowned upon in professional code as the performance penalty is generally unacceptable (in most cases).

    We are using As New shortcut only if the reference is going to be used for a single method call. For instance Dim oFrm As New MyForm : If oFrm.ShowForm(...) Then ... sole usage of the variable.

    cheers,
    </wqw>

  18. #18

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2022
    Posts
    334

    Re: Confusion about Interfaces

    The rule is simple: Dim with interface, New with coclass.
    Makes sense as every vb* programmer knows and does work with CoClasses and Interfaces belonging to the StdOle libray as we have seen so far.

    However, applying exactly the same logic to the MS excel library doesn't seem to work .
    Code:
    Dim oWB As Excel.Workbook
    Set oWB = New Excel.Workbook  '<== Error : Class not registered
    Code:
    Dim oWS As Excel.Worksheet
    Set oWS = New Excel.Worksheet '<== Error : Class doesn't support automation or doesn't support expected inteface.
    Despite Workbook and Worksheet, both being creatable CoClasses and both having Dual Default interfaces inheriting from IDispatch as shown in the attached images below.

    This seems to clash with the above mentioned rule. So what's going on then?


    Name:  Unti8888888tled.png
Views: 149
Size:  15.9 KB

    Name:  Un101010titled.png
Views: 155
Size:  16.3 KB
    Last edited by AngelV; Apr 17th, 2024 at 10:50 PM.

  19. #19

  20. #20
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,895

    Re: Confusion about Interfaces

    Quote Originally Posted by AngelV View Post
    Makes sense as every vb* programmer knows and does work with CoClasses and Interfaces belonging to the StdOle libray as we have seen so far.

    However, applying exactly the same logic to the MS excel library doesn't seem to work .
    Code:
    Dim oWB As Excel.Workbook
    Set oWB = New Excel.Workbook  '<== Error : Class not registered
    Code:
    Dim oWS As Excel.Worksheet
    Set oWS = New Excel.Worksheet '<== Error : Class doesn't support automation or doesn't support expected inteface.
    Despite Workbook and Worksheet, both being creatable CoClasses and both having Dual Default interfaces inheriting from IDispatch as shown in the attached images below.

    This seems to clash with the above mentioned rule. So what's going on then?
    Something is very wrong with Office typelibs in general. The above "rule" is how the language is designed to work.

    My test:

    Code:
    Option Explicit
    
    Sub Test()
        Debug.Print TypeName(New Excel.Application)
        Debug.Print CreateObject("Excel.Application").Version
        Debug.Print TypeName(New Excel.Chart)
        Debug.Print TypeName(CreateObject("Excel.Chart"))
        Debug.Print TypeName(New Excel.OLEObject)
        Debug.Print TypeName(CreateObject("Excel.OLEObject"))
        Debug.Print TypeName(New Excel.QueryTable)
        Debug.Print TypeName(CreateObject("Excel.QueryTable"))
        Debug.Print TypeName(New Excel.Workbook)
        Debug.Print TypeName(CreateObject("Excel.Workbook"))
        Debug.Print TypeName(New Excel.Worksheet)
        Debug.Print TypeName(CreateObject("Excel.Worksheet"))
    End Sub
    First line on my machine says "Error in loading DLL" but this doesn't contradict the rule.

    Second line prints "15.0" so there is Excel.Application somewhere installed.

    Btw, I never said "New with coclass" will always succeed. It's more about "New with interface" cannot even compile :-))

    Btw, CreateObject with Workbook/Worksheet fails here too.

    cheers,
    </wqw>

  21. #21

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2022
    Posts
    334

    Re: Confusion about Interfaces

    Code:
     Debug.Print TypeName(CreateObject("Excel.Worksheet"))
    doesn't work (error : ActiveX component can't create object)

    But the following works, although it yields Workbook instead of Worksheet !
    Code:
     Debug.Print TypeName(CreateObject("Excel.Sheet"))

  22. #22
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,895

    Re: Confusion about Interfaces

    Quote Originally Posted by AngelV View Post
    Code:
     Debug.Print TypeName(CreateObject("Excel.Worksheet"))
    doesn't work (error : ActiveX component can't create object)

    But the following works, although it yields Workbook instead of Worksheet !
    Code:
     Debug.Print TypeName(CreateObject("Excel.Sheet"))
    Office is bonkers!

    Cannot imagine what one can do with such "detached" worksheet.

    cheers,
    </wqw>

  23. #23

    Thread Starter
    Hyperactive Member
    Join Date
    Jun 2022
    Posts
    334

    Re: Confusion about Interfaces

    Thanks a lot guys. I have learnt so much from you

Posting Permissions

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



Click Here to Expand Forum to Full Width