I would like to create an Interface that implements multiple interfaces, and then make a class that implements that interface. For example:
IFlyable module:
Public Sub Fly()
End Sub
Public Function GetAltitude() As Long
End Function
ISwimmable module:
Public Sub Swim()
End Sub
Public Function GetDepth() As Long
End Function
IFlySwim module:
Implements IFlyable
Implements ISwimmable
Public Sub IFlyable_Fly()
End Sub
Public Function IFlyable_GetAltitude() As Long
End Function
Public Sub ISwimmable_Swim()
End Sub
Public Function ISwimmable_GetDepth() As Long
End Function
This all compiles just fine. But if I declare an Object of type IFlySwim, the predictive text in VBA gives me:
And trying to create a Class that implements IFlySwimmable just doesn't work.
Class Duck:
Implements IFlySwim
Public Sub IFlySwim_IFlyable_Fly()
Debug.Print "Flying with wings!"
End Sub
Public Function IFlySwim_IFlyable_GetAltitude() As Long
IFlySwim_IFlyable_GetAltitude = 30
End Function
Public Sub IFlySwim_ISwimmable_Swim()
Debug.Print "Swimming with feet!"
End Sub
Public Function IFlySwim_ISwimmable_GetDepth() As Long
IFlySwim_ISwimmable_GetDepth = 20
End Function
Pressing the compile button gives me the error: "Compile error: Object module needs to implement 'IFlyable_Fly' for interface 'IFlySwim'.
So this leads me to believe that Implement
ing an interface within another interface Doesn't Work. Or at least, it doesn't make sense from VBA's point of view. Which is understandable, because I'm not actually providing an implementation for IFlyable
and ISwimmable
in IFlySwim
. What I really want to do is defer implementation for IFlyable
and ISwimmable
to a class that implements both of them.
So now, if my Duck
class is:
Implements IFlyable
Implements ISwimmable
Public Sub IFlyable_Fly()
Debug.Print "Flying with wings!"
End Sub
Public Function IFlyable_GetAltitude() As Long
IFlyable_GetAltitude = 30
End Function
Public Sub ISwimmable_Swim()
Debug.Print "Swimming with feet!"
End Sub
Public Function ISwimmable_GetDepth() As Long
ISwimmable_GetDepth = 20
End Function
Then when I go to use it, the predictive dropdown gives me:
I could cast Duck
to either the IFlyable
or ISwimmable
to use as such:
But what if I wanted to create a Function or Sub that accepts a Flyable/Swimmable? Do I have to create a completely separate interface called IFlySwim that contains all of the Sub/Functions from IFlyable
and ISwimmable
, and then modify my Duck
class to only implement from the IFlySwim
?
Unfortunately, that is how inheritance by composition works. However you should realise that your Duck class is tying the interface to the concrete implementation of the function implementations. You need to use a second level of indirection
Implements IFlyable
Implements ISwimmable
Private Sub IFlyable_Fly()
Fly
End Sub
|Private Function IFlyable_GetAltitude() As Long
IFlyable_GetAltitude=GetAltitude
End Function
Private Sub ISwimmable_Swim()
Swim
End Sub
Private Function ISwimmable_GetDepth() As Long
ISwimmable=GetDepth
End Function
Public Sub Fly()
Debug.Print "Flying with wings!"
End Sub
Public Function GetAltitude() As Long
GetAltitude = 30
End Function
Public Sub Swim()
Debug.Print "Swimming with feet!"
End Sub
Public Function GetDepth() As Long
GetDepth = 20
End Function
From this you can see that GetAltitude and GetDepth could both refer to a property of VerticalPosition
Private Function IFlyable_GetAltitude() As Long
IFlyable_GetAltitude=GetVerticalPosition
End Function
Private Function ISwimmable_GetDepth() As Long
ISwimmable_GetDepth=- GetVerticalPosition
End function
Which may or may not be helpful top you.
Interface methods/properties (ie methods/properties prefixed with an underscore) should not be exposed as public. They must be implemented to fulfill the contract of the interface in the derived class, but they should be marked as private. Once you have done so, you can expose public members with method names like Fly
or GetAltitude
(see below):
Option Explicit
Implements ISwimmable
Implements IFlyable
'********************************************************
'Public Methods
'********************************************************
Public Function GetDepth() As Long
GetDepth = 10
End Function
Public Sub Swim()
Debug.Print "Swimming!"
End Sub
Public Function GetAltitude() As Long
GetAltitude = 50
End Function
Public Sub Fly()
Debug.Print "Flying with wings!"
End Sub
'********************************************************
'Private Methods
'********************************************************
Private Function ISwimmable_GetDepth() As Long
End Function
Private Sub ISwimmable_Swim()
End Sub
Private Function IFlyable_GetAltitude() As Long
End Function
Private Sub IFlyable_Fly()
End Sub
And your test code becomes the following: (see below)
Sub InterfaceTest()
Dim ducky As New Duck
ducky.Fly
Debug.Print ducky.GetAltitude()
ducky.Swim
Debug.Print ducky.GetDepth()
End Sub
But what if I wanted to create a Function or Sub that accepts a Flyable/Swimmable? Do I have to create a completely separate interface called IFlySwim that contains all of the Sub/Functions from IFlyable and ISwimmable, and then modify my Duck class to only implement from the IFlySwim?
Short answer: Yes.
Why?
Because, VBA/VB6 does not support inheritance fully. To do what you ask, you would have create a third class that inherits from ISwimmable
and IFlyable
, and then implement that class in other classes.
In a fully OOP language like C#
, you could to the following: (see below)
public interface IFlyable {
void Fly();
int GetAltitude();
}
public interface ISwimmable {
void Swim();
int GetDepth();
}
//Base Class
public abstract class BaseDuck: ISwimmable, IFlyable {
public BaseDuck(){}
public void Fly() {
Console.WriteLine("Flying with wings!");
}
public virtual int GetAltitude() {
return 50;
}
public void Swim() {
Console.WriteLine("Swimming!");
}
public virtual int GetDepth() {
return 10;
}
}
//Derived Class
public class SeaDuck: BaseDuck {
public SeaDuck(){}
public override int GetAltitude() {
return 50;
}
public override int GetDepth() {
return 100;
}
public void RideWaves() {
Console.WriteLine("Riding waves!");
}
}
//Derived Class
public class MallardDuck: BaseDuck {
public MallardDuck(){}
public override int GetAltitude() {
return 100;
}
public override int GetDepth() {
return 10;
}
public void HeadToLandForWinter() {
Console.WriteLine("Headed for land!");
}
}
Using the following to test: (see below)
using System;
public class Program
{
public static void Main()
{
SeaDuck seaDuck = new SeaDuck();
Console.WriteLine("Sea Duck:");
seaDuck.Fly();
Console.WriteLine(seaDuck.GetAltitude().ToString());
seaDuck.Swim();
Console.WriteLine(seaDuck.GetDepth().ToString());
seaDuck.RideWaves();
Console.WriteLine("\n");
Console.WriteLine("Mallard Duck:");
MallardDuck mallardDuck = new MallardDuck();
mallardDuck.Fly();
Console.WriteLine(mallardDuck.GetAltitude().ToString());
mallardDuck.Swim();
Console.WriteLine(mallardDuck.GetDepth().ToString());
mallardDuck.HeadToLandForWinter();
}
}
Produces:
Sea Duck:
Flying with wings!
50
Swimming!
100
Riding waves!
Mallard Duck:
Flying with wings!
100
Swimming!
10
Headed for land!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.