• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 342
  • Last Modified:

Events in class which Implements interface

I am trying to create the abstract "parent" class and 10 "descendant" classes. Each Implements "ancestor" interface. In main form I need to create and use an instance of one of the 10 classes depending on the user's choice.
How to use events? I tried to declare events like that
Public Event Error(Msg As String)
in both abstract class (clsConverter) and descendant. But when I declare
Private WithEvents Converter As clsConverter
and try to create
Set Converter = New clsDescConverter
I got the error message with the following help
"You tried to use a WithEvents variable with a component that can't work as an event source for the specified set of events. For example, you may be sinking events of an object, then create another object that Implements the first object. Although you might think you could sink the events from the implemented object, that isn't automatically the case. Implements only implements an interface for methods and properties.

You can't sink events for a component that doesn't source events."
What could be the possible solution of this problem?
  • 3
  • 3
  • 2
  • +1
1 Solution
I think you would have to have an object reference to the clsDescConverter in order to sink its events. This reference would have to be of the clsDescConverter type not the clsConverter type. The clsConverter doesn't know the interface of clsDescConverter and therefore cannot sink its events.

dksqrtAuthor Commented:
But having to declare all descendants WithEvents instances and sink is a nightmare!
I have 10 classes and 4 events I would have to write 10 declarations and 40 handlers! 40 handlers which do *the same* handling!
Any other ideas? I can reorganize code any way I want to but writing 10 copies of the same procedure - it's just disgusting from the OOP and even structured programming point of view...
What does "isn't automatically the case" in the previous help message mean? Perhaps some solution is possible?
And all my 4 events are *declared* in clsConverter and
clsDescConverter **Implements** clsConverter interface.
Why "The clsConverter doesn't know the interface of clsDescConverter and therefore cannot sink its events." ?
Have one class CMainClass which fires the events and does any computation common to call classes and has a property which is an IConverter object (ie class implementing the IConverter interface). You can sink events from this class. To allow for the difference in converters you set the IConverter parameter of the CMainClass to be clsDescConverter say. Then when CMainClass needs to do anything it can call the methods of the clsDescConverter class you passed it.

Suppose that you define a Convert method in the IConverter interface.
Give the CMainClass a property of type IConverter, call it converter.
Suppose you want to use the clsDescConverter. You set the CMainClass.Converter property to a clsDescConverter object.
Then when you call the Convert method of the CMainClass object, it would call the converter objects Convert method (which would be there because it is a part of the IConverter interface).

Hope this helps.
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

I've just realised I left an unanswered question.

clsDescConverter implements the clsConverter interface which is how it knows what that interface is. The clsConverter is the base object. It doesn't know anything about the clsDescConverter objects interface.
dksqrtAuthor Commented:
Yes it is unanswered
There is not a solution to this problem.
This has to do with the way COM works and the way VB implements events. The events and the method are actually two different objects in COM.
With implements you implements only the method and the properties. You cannot inherited the events.
dksqrtAuthor Commented:
I got your point. But could you suggest any posiible workaround?
I have the pretty concrete task and I can design all involved classes anyway I want.
If it's not possible to have RaiseEvent-s in inherited classes - how to live without them?
Pass the parent object to the interface.

clsConverter.Init me

and make the caller implement clsConverterCallback interface.
These are the event methods.

You can implement the following workaround:

1. Create the parent object (Public Inherited As clsConverter) in each child. (in child's Class_Initialize())
2. Implement interface as usual without events.
3. Define events in the parent and create one additional procedure for each event in the parent class.

Public Sub RaiseMessage(Msg As String)
  RaiseEvent Message(Msg)
End Sub
4. Copy and paste these procedures in each child replacing the call inside to Call Inherited.RaiseMessage(Msg).
5. Replace all occurences of RaiseEvent Message(Msg)
in child classes to RaiseMessage(Msg)
6. Sink events in the form you need (such as the main form of a program) like this:

Private WithEvents GenConverter As clsConverter
Set Converter = New clsDescConverter
Set GenConverter = Converter.Inherited
'Ready to work - events will be sinked
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 3
  • 3
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now