2

I have two separate classes (A = a subclass of BevelButtom, B = a subclass of PushButton). Both A and B implement a number of identical methods in exactly the same way. Since both subclasses' superclasses are different and since RB doesn't support multiple inheritance, all I can do to tie these methods together is define a class interface, have both subclasses implement the interface, then copy/paste the method bodies in each subclass.

That offends my sensibilities. Is there a way in RB to extract this common logic elsewhere?

Thanks!

dda
  • 6,030
  • 2
  • 25
  • 34
ABach
  • 3,743
  • 5
  • 25
  • 33

2 Answers2

3

Use the Extends syntax from a module method to extend the class interface. You still need to use a class interface, but this way all the common code can be placed in the module instead of being duplicated across multiple classes.

Interface FooInterface
  Sub Foo()
End Interface

Class Foo
Implements FooInterface
  Sub Foo()
    MsgBox("Foo!")
  End Sub
End Class

Class Bar
Implements FooInterface
  Sub Foo()
    MsgBox("Bar!")
  End Sub
End Class

Module FooExtensions
  Sub Foobar(Extends FooImplementor As FooInterface)
    MsgBox("Foobar!")
  End Sub
End Module

The above FooBar method would be called like a class method of any class that implements the FooInterface class interface:

Dim myfoo As FooInterface = New Bar
myfoo.Foobar()

Note that extension methods don't count when the compiler is deciding whether a given class satisfies an interface.

This may not be workable, however, since the extension methods will only have access to the Interface rather than the actual class.

Alternatively, you could extend the RectControl class, though that would include all desktop controls, not just the PushButton and BevelButton.

A third option might be to use the BevelButton class exclusively.

Andrew Lambert
  • 1,869
  • 1
  • 17
  • 31
  • Thank you for your answer. Unfortunately, I *do* need access to the individual classes (as they have some common properties). I suppose I could have the extension methods cast their interface to the specific class (using judicious amounts of `IsA`), but that still feels gnarly... – ABach Jan 04 '13 at 13:46
  • Your answer has helped a ton. I'm accepting Paul's answer because it adheres slightly more to my exact scenario, but I much appreciate your effort. If I could award two answers, I would in a heartbeat. – ABach Jan 04 '13 at 17:54
2

Using an interface seems like the right approach, but rather than copying the method bodies to each subclass, I think it makes more sense to create a new class (say CommonButtonStuff) with the common code. Then you can call it in the implemented methods:

CommonButtonInterface
  Sub Method1

Class CommonButtonHandler
  Sub DoMethod1
    MsgBox("Do it!")
  End Sub

Class A Inherits From PushButton, Implements CommonButtonInterface
  Private Property mCommonStuff As CommonButtonHandler

  Sub Constructor
    mCommonStuff = New CommonButtonHandler
  End Sub

  Sub Method1
    mCommonStuff.DoMethod1
  End Sub

Class B Inherits From BevelButton, Implements CommonButtonInterface
  Private Property mCommonStuff As CommonButtonHandler

  Sub Constructor
    mCommonStuff = New CommonButtonHandler
  End Sub

  Sub Method1
    mCommonStuff.DoMethod1
  End Sub
Paul Lefebvre
  • 6,253
  • 3
  • 28
  • 36
  • Thank you, Paul - I appreciate hearing back from you! If you don't mind, a quick question: what do you like about this method vs. the Module method described by @Amazed? – ABach Jan 04 '13 at 17:24
  • I guess it depends what you need to do. Classes are more powerful than modules and have their own instances so they would allow you to design something more robust. Heck, you could combine both techniques so that you Extend PushButton and BevelButton separately, but have them call common code in a module or class and forego the interface. – Paul Lefebvre Jan 04 '13 at 17:39
  • Got it. That makes a lot of sense (and this morning, I had a similar thought about classes being more robust); plus, if interfaces are merely to define implementation-less contracts, then their use in this scenario bothers me. Thanks so much! – ABach Jan 04 '13 at 17:52