|
Dit artikel is gepubliceerd op zondag 31 juli 2011 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.
21.1.1. Aanwezig van Members Afdwingen via Abstracte KlassenAbstract Base Classes ( ABCs ) kunnen we definiëren zodoende in de hiervan afgeleide klassen de aanwezigheid van bepaalde members af te dwingen. Hiervoor maken we gebruik van MustOverride members die verplicht overschreven moeten worden in de concrete ( niet abstracte ) afgeleide klassen : Visual Basic 2010 Broncode Option Strict OnOption Explicit OnNamespace Example1 MustInherit Class Class1 Public MustOverride Sub Command1() Public MustOverride Function Query1() As String Public MustOverride Property Property1() As String End Class Class Class2 : Inherits Class1 Public Overrides Sub Command1() Console.WriteLine( "Class2.Command1()") End Sub Public Overrides Function Query1() As String Query1 = "Class2.Query1()" End Function Public Overrides Property Property1() As String Get Return "Class2.Property1" End Get Set( ByVal value As String) End Set End Property End Class Class Class3 : Inherits Class1 Public Overrides Sub Command1() Console.WriteLine( "Class3.Command1()") End Sub Public Overrides Function Query1() As String Query1 = "Class3.Query1()" End Function Public Overrides Property Property1() As String Get Return "Class3.Property1" End Get Set( ByVal value As String) End Set End Property End Class Class Client Public Shared Sub Main() Dim object1 As Class1 object1 = New Class2 object1.Command1() Console.WriteLine(object1.Query1()) Console.WriteLine(object1.Property1()) object1 = New Class3 object1.Command1() Console.WriteLine(object1.Query1()) Console.WriteLine(object1.Property1()) Console.ReadLine() End Sub End ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output Class2.Command1()
Class2.Query1()
Class2.Property1
Class3.Command1()
Class3.Query1()
Class3.Property1 Eender welk object waarnaar een variabele gedeclareerd van het type Class1 kan wijzen zal nu zeker over implementaties beschikken voor :
- Public Sub Command1() - Public Function Query1() As String - Public Property Property1() As String boven
21.1.2. Aanwezigheid van Members Afdwingen via InterfacesEen alternatief voor het gebruik van abstracte basis klassen met enkel MustOverride members is een "interface".
In een interfacetype definieer je de interface van de members waarvan je wenst dat in de klassen - die dat interfacetype "implementeren" - een implementatie wordt gekoppeld aan die memberinterface.
Een interfacetype ( of dus een abstracte basis klasse met enkel MustOverride members ) is een soort van contract dat je definieert. Je definieert hierin dus aan wat voldaan moet zijn ( in de afgeleiden of "implementeerders" ), maar niet hoe dit afgehandeld dient te worden ( dus niet de implementatie ).
Een interface wordt geïmplementeerd ( en niet overgeërfd ). Een Implements clausule wordt gebruikt om aan te geven dat een type implementaties zal/moet voorzien voor alle members uit die interface.
Ook bij implementatie wordt via een Implements clausule aangegeven welke member uit het interfacetype wordt geïmplementeerd. Visual Basic 2010 Broncode Namespace Example2 Interface Class1 Sub Command1() Function Query1() As String Property Property1() As String End Interface Class Class2 : Implements Class1 Public Sub Command1() Implements Class1. Command1 Console.WriteLine( "Class2.Command1()") End Sub Public Function Query1() As String Implements Class1. Query1 Query1 = "Class2.Query1()" End Function Public Property Property1() As String Implements Class1. Property1 Get Return "Class2.Property1" End Get Set( ByVal value As String) End Set End Property End Class Class Class3 : Implements Class1 Public Sub Command1() Implements Class1. Command1 Console.WriteLine( "Class3.Command1()") End Sub Public Function Query1() As String Implements Class1. Query1 Query1 = "Class3.Query1()" End Function Public Property Property1() As String Implements Class1. Property1 Get Return "Class3.Property1" End Get Set( ByVal value As String) End Set End Property End Class Class Client Public Shared Sub Main() Dim object1 As Class1 object1 = New Class2 object1.Command1() Console.WriteLine(object1.Query1()) Console.WriteLine(object1.Property1()) object1 = New Class3 object1.Command1() Console.WriteLine(object1.Query1()) Console.WriteLine(object1.Property1()) Console.ReadLine() End Sub End ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output Class2.Command1()
Class2.Query1()
Class2.Property1
Class3.Command1()
Class3.Query1()
Class3.Property1 Merk op dat enkel de signatuur van members wordt opgenomen in het interfacetype, en dat hierbij geen Access modifier wordt vermeld. Over dit laatste in een volgend voorbeeld meer.
Volgend contextvoorbeeld geeft aan hoe je met een abstracte basis klasse, die het generalisatietype is voor de elementen van een collectie, ervoor kunt zorgen dat alle specifieke element types over bepaalde members beschikken.
Onderstaand voorbeeld maakt gebruik van System.Collections.CollectionBase. Dit datatype is bruikbaar om reeds enkele typische voorzieningen voor collecties ( members als Count, RemoveAt, Clear, ... ) van over te erven. Voor meer details over dit datatype vind je in het desbetreffende topic. Visual Basic 2010 Broncode Namespace WithMustInheritClass MustInherit Class Figure Public MustOverride Function GetArea() As Double End Class Class Figures : Inherits CollectionBase Public Sub Add( ByVal item As Figure) List.Add(item) End Sub Public ReadOnly Property Item( ByVal index As Integer) As Figure Get Item = DirectCast(List.Item(index), Figure) End Get End Property Public Function GetTotaleArea() As Double For Each item As Figure In List GetTotaleArea += item.GetArea() Next End Function End Class Class Square : Inherits Figure Private m_Side As Double Public Property Side() As Double Get Side = m_Side End Get Set( ByVal Value As Double) m_Side = Value End Set End Property Public Overrides Function GetArea() As Double GetArea = Side ^ 2 End Function End Class Class Circle : Inherits Figure Private m_Radius As Double Public Property Radius() As Double Get Radius = m_Radius End Get Set( ByVal Value As Double) m_Radius = Value End Set End Property Public Overrides Function GetArea() As Double GetArea = (Radius ^ 2) * System.Math.PI End Function End Class Class Client Public Shared Sub Main() Dim figures1 As Figures = New Figures figures1.Add( New Square With {.Side = 5}) figures1.Add( New Circle With {.Radius = 1}) Console.WriteLine(figures1.GetTotaleArea()) Console.ReadLine() End Sub End ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output 28,1415926535898 Dit is een illustratie van een typische situatie waarin het afdwingen van de aanwezigheid van members van toepassing zou zijn.
Doordat collectietype Figures enkel kan werken met elementen van het type Figure ( of een afgeleid type ) en niets anders ( Sub Add(item As Figure) ) kan er in Figures er probleemloos vanuit worden gegaan dat alle itemobjecten beschikken over een de nodige members ( GetArea() ) om vervolgens de GetTotaleArea() te berekenen.
Vorig voorbeeld kan ook aan de hand van een interfacetype worden opgelost. Visual Basic 2010 Broncode Namespace WithInterface Interface IFigure Function GetArea() As Double End Interface Class Figures : Inherits CollectionBase Public Sub Add( ByVal item As IFigure) List.Add(item) End Sub Public ReadOnly Property Item( ByVal index As Integer) As IFigure Get Item = DirectCast(List.Item(index), IFigure) End Get End Property Public Function GetTotaleArea() As Double For Each item As IFigure In List GetTotaleArea += item.GetArea() Next End Function End Class Class Square : Implements IFigure Private m_Side As Double Public Property Side() As Double Get Side = m_Side End Get Set( ByVal Value As Double) m_Side = Value End Set End Property Public Function GetArea() As Double Implements IFigure. GetArea GetArea = Side ^ 2 End Function End Class Class Circle : Implements IFigure Private m_Radius As Double Public Property Radius() As Double Get Radius = m_Radius End Get Set( ByVal Value As Double) m_Radius = Value End Set End Property Public Function GetArea() As Double Implements IFigure. GetArea GetArea = (Radius ^ 2) * System.Math.PI End Function End Class Class Client Public Shared Sub Main() Dim figures1 As Figures = New Figures figures1.Add( New Square With {.Side = 5}) figures1.Add( New Circle With {.Radius = 1}) Console.WriteLine(figures1.GetTotaleArea()) Console.ReadLine() End Sub End ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output 28,1415926535898 Het IFigure datatype wordt hier als element type gebruikt.
Merk ook op dat het type hier IFigure is genoemd en niet gewoon Figure, meerdere naming conventions stellen dat het duidelijker is interfacetypes een "I" prefix te geven in hun identifier. Ook in alle volgende voorbeelden en oefeningen zal de prefix "I" voor interfacetypes worden gebruikt. Overigens wordt er ook vaak een suffix "able" gebruikt in de identifiers van interfacetypes.
Dit artikel is gepubliceerd op zondag 31 juli 2011 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.
|