homeboekenlinksledenabonneer je :Blijf op de hoogte door je te abonneren op de vbvoorbeelden RSS Niews Feed!Blijf op de hoogte door vbvoorbeelden te volgen op Twitter!Blijf op de hoogte door fan te worden van vbvoorbeelden op Facebook!
Visual Basic 2008 en 2010 Voorbeelden en Boeken Microsoft Visual Studio 2010Microsoft Developers Network - Visual BasicMicrosoft .NET Framework

visual basic 2008 voorbeelden en boeken / visual basic 2010 voorbeelden en boeken

9.13. Redefinition - Overridable en Overrides

Print Email Deel op FacebookDeel op TwitterDeel op DiggBookmark op Google BookmarksDeel op del.icio.usOverige Sociale Netwerksites...

Dit artikel is gepubliceerd op woensdag 28 april 2010 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.

9.13.1. Overridable en Overrides

Wanneer men aan een overgeërfde member een andere implementatie wenst te koppelen kan men deze overgeërfde member gaan herdefiniëren. Dit wordt ook wel "redefinition" of in de context van Visual Basic "overriding" genoemd.

Een vereiste is wel dat de member die je wenst te herdefiniëren in de basisklasse als herdefinieerbaar staat aangegeven.
Dit kan door in de signatuur van deze member het Overridable keyword op te nemen.

De member wordt herhaald in de klassen die aan deze member een andere implementatie willen koppelen en staat daar als herdefinitie aangegeven. Wat men bekomt door aan de signatuur van deze herdefinitie het Overrides keyword toe te voegen.
Visual Basic Broncode
Class Class1
    Public Overridable Function Method1() As String
        Method1 = "Class1.Method1()"
    End Function
End Class
Class Class2 : Inherits Class1
    Public Overrides Function Method1() As String
        Method1 = "Class2.Method1()"
    End Function
End Class
Module Example1
    Sub Main()
        Dim object1 As Class1 = New Class1
        Console.WriteLine(object1.Method1())                               ' (1)
        '
        Dim object2 As Class2 = New Class2
        Console.WriteLine(object2.Method1())                               ' (2)
        '
        Console.ReadLine()
    End Sub
End Module
Visual Basic Output
Class1.Method1()
Class2.Method1()
Tijdens uitvoering van de client zal de aanroep op regel (1) "Class1.Method1()" als resultaat geven, en dit omdat object1 een object is van het type Class1.
Regel (2) zal dan als uitvoer "Method1 defined in Class2" geven, gezien de expressie object2 verwijst naar een object van het type Class2.

Vergeet het keyword Overrides niet in de signatuur van de herdefiniërende member, anders bekomt men geen redefinition maar shadowing.

Redefinition houdt dus steeds in dat een andere implementatie wordt gekoppeld aan de interface ( lees aanwezigheid ) van die member in een bepaald afgeleid type. Het spreekt dan ook voor zich dat enkel implementatiemembers ( properties en methods ) kunnen geherdefinieerd worden.

Velden bijvoorbeeld die niet beschikken over een implementatie, kunnen bijgevolg ook niet gekoppeld worden aan een andere implementatie, redefinition van velden is dan ook onmogelijk.

Ook Private members kunnen niet worden geherdefinieerd. Private members worden overgeërfd maar zijn niet aanroepbaar in afgeleide types, dus moet men geen andere implementatie kunnen koppelen aan die members wanneer die worden aangeroepen op of door een object van een afgeleid type.

Public- en Protected members zijn wel aanroepbaar in of op objecten van een afgeleid type, dus kan het wel nuttig zijn om aan deze aanroep een andere betekenis ( implementatie ) te gaan koppelen.

9.13.2. NotOverridable

Een overschrijvende ( herdefiniërende ) members is zelf by default ook overschrijfbaar ( herdefinieerbaar ). Of met ander woorden Overrides impliceert ook Overridable.
Zo zal in onderstaand voorbeeld de herdefinitie (1) van Method1 zonder argumenten in Class4, ook nog eens geherdefinieerd worden in Class5, en dit zonder dat in Class4 Method1 expliciet als Overridable stond gemarkeerd.

Wenst men dit default gedrag aan te passen, dan kan men in de signatuur het NotOverridable keyword aan het Overrides keyword gaan toevoegen.

In onderstaand voorbeeld zal Method1 ( met 1 argument ) uit Class4 niet herdefinieerbaar zijn in Class5.
Visual Basic Broncode
Class Class3
    Public Overridable Function Method1() As String
        Method1 = "Class3.Method1()"
    End Function
    Public Overridable Function Method1(ByVal argument As String) As String
        Method1 = "Class3.Method1(" & argument & ")"
    End Function
End Class
Class Class4 : Inherits Class3
    Public Overrides Function Method1() As String ' (1)
        Method1 = "Class4.Method1()"
    End Function
    Public NotOverridable Overrides Function Method1(ByVal argument As String) _
                                                                       As String
        Method1 = "Class4.Method1(" & argument & ")"
    End Function
    Public Overloads Function Method1(ByVal argument1 As String, _
                                      ByVal argument2 As String) As String
        Method1 = "Class4.Method1(" & argument1 & "," & argument2 & ")"
    End Function
End Class
Class Class5 : Inherits Class4
    Public Overrides Function Method1() As String
        Method1 = "Class5.Method1()"
    End Function
End Class
Module Example2
    Sub Main()
        Dim object1 As Class3 = New Class3
        Console.WriteLine(object1.Method1())
        Console.WriteLine(object1.Method1("test"))
        '
        Dim object2 As Class4 = New Class4
        Console.WriteLine(object2.Method1())
        Console.WriteLine(object2.Method1("test"))
        Console.WriteLine(object2.Method1("test1", "test2"))
        '
        Dim object3 As Class5 = New Class5
        Console.WriteLine(object3.Method1())
        Console.WriteLine(object3.Method1("test"))
        Console.WriteLine(object3.Method1("test1", "test2"))
        '
        Console.ReadLine()
    End Sub
End Module
Visual Basic Output
Class3.Method1()
Class3.Method1(test)
Class4.Method1()
Class4.Method1(test)
Class4.Method1(test1,test2)
Class5.Method1()
Class4.Method1(test)
Class4.Method1(test1,test2)
In Class4 werd een extra versie van Method1 toegevoegd ( met 2 argumenten ), vergeet men hierbij het keyword Overloads te vermelden, dan krijgt men een compileerfout.
Een extra versie van een overgeërfde member die men wil toevoegen aan een afgeleide klasse moet immers altijd met het Overloads keyword gemarkeerd worden.

Hieronder een context voorbeeld waar geïllustreerd wordt dat het koppelen van een andere betekenis ( of implementatie ) aan een member nut kan hebben voor afgeleide klassen.

We beschikken over een Counter klasse, die bruikbaar is om een Value met 1 te incrementeren ( Raise ) of met 1 te decrementeren ( Lower ).
Visual Basic Broncode
Class Counter
    Protected m_Value As Integer
    Public ReadOnly Property Value() As Integer
        Get
            Value = m_Value
        End Get
    End Property
    Public Overridable Sub Raise()
        m_Value += 1
    End Sub
    Public Overridable Sub Lower()
        m_Value -= 1
    End Sub
End Class
Module Example3
    Sub Main()
        Dim counter As Counter = New Counter
        Console.WriteLine(counter.Value)
        counter.Raise()
        Console.WriteLine(counter.Value)
        counter.Raise()
        Console.WriteLine(counter.Value)
        counter.Lower()
        Console.WriteLine(counter.Value)
        '
        Console.ReadLine()
    End Sub
End Module
Visual Basic Output
0
1
2
1
Het schiet ons te binnen dat we ook een soort van Counter zouden kunnen gebruiken waar niet steeds stap waarde 1 wordt gebruikt om de Value te verhogen of verlagen.

We beslissen hiervoor een type SpecialCounter te creëren.

Het dringt tot ons door dat we SpecialCounter kunnen afleiden van Counter. Een SpecialCounter IS tenslotte een specialisatie van de Counter die we reeds hebben, en SpecialCounter kan de aanwezigheid van alle members uit Counter gebruiken.

Gezien een stapwaarde moet kunnen worden gebruikt door onze SpecialCounter objecten, beslissen we een StepValue eigenschap toe te voegen aan deze afgeleide klasse.

Het gedrag ( dat we ook overerven van Counter ) dat ervoor zorgt dat bij het verhogen ( Raise ) of verlagen ( Lower ) steeds de Value met 1 respectievelijk gaat incrementeren of decrementeren, moet echter aangepast worden. De ( aanwezigheid van de ) Raise- en Lower methods zijn/is nuttig voor SpecialCounter, enkel het gedrag ervan ( of dus de implementaties ) zijn voor het gespecialiseerde type niet bruikbaar en moet gewijzigd/geherdefinieerd worden.
Visual Basic Broncode
Class SpecialCounter : Inherits Counter
    Private m_StepValue As Integer = 1
    Public Property StepValue() As Integer
        Get
            StepValue = m_StepValue
        End Get
        Set(ByVal value As Integer)
            m_StepValue = value
        End Set
    End Property
    Public Overrides Sub Raise()
        m_Value += StepValue
    End Sub
    Public Overrides Sub Lower()
        m_Value -= StepValue
    End Sub
End Class
Hadden we in eerste instantie de Raise- en Lower methods niet Overridable gedefinieerd, dan was het niet mogelijk om het gedrag van deze methods te wijzigen in afgeleide klassen.

Men dient er zich dus steeds bij stil te staan ( bij het creëren van een afleidbare basisklasse ) of het nuttig kan zijn dat afgeleiden bepaalde implementatiemembers gaan herdefiniëren. Is dit nuttig, markeer die member dan meteen als herdefinieerbaar ( Overridable ).

Het zelfde kan gesteld worden voor de access modifiers die je gebruikt in de afleidbare basisklassen. Gezien de Raise- en Lower methods herdefinieerbaar werden gedefinieerd in Counter en gezien deze methods de waarde van het veld m_Value ( de toestand Value ) aanpassen, is het ook logisch de velden ( hier veld m_Value ) die mogelijk gemanipuleerd worden door die herdefinieerbare members beschikbaar te maken voor de afgeleiden.
Bij ingekapselde members kan dit bijvoorbeeld door access modifier Protected te gebruiken.
Visual Basic Broncode
Module Example4
    Sub Main()
        Dim specialCounter As SpecialCounter = New SpecialCounter
        Console.WriteLine(specialCounter.Value)
        specialCounter.StepValue = 5
        specialCounter.Raise()
        Console.WriteLine(specialCounter.Value)
        specialCounter.Raise()
        Console.WriteLine(specialCounter.Value)
        specialCounter.Lower()
        Console.WriteLine(specialCounter.Value)
        '
        Console.ReadLine()
    End Sub
End Module
Visual Basic Output
0
5
10
5

9.13.3. System.Object.ToString()

We weten reeds dat elke klasse op zen minst een afgeleide is van het algemeen overkoepelend basistype System.Object. Wordt er niet expliciet een Inherits clausule toegevoegd aan een klassedefinitie, dan wordt er immers Inherits System.Object aan toegevoegd.

Een afgeleide klasse erft de members over van de basisklasse.

System.Object is niet leeg, met andere woorden van System.Object zullen bepaalde members worden overgeërfd.
Een voorbeeld van dergelijke overgeërfde member is : Public Overridable Function ToString() As String. Deze member heeft als defaultgedrag dat het de "fully-qualified-identifier" van de klasse ( volledige naam van de klasse, inclusief onderdeel waarin die klasse is gedefinieerd ) oplevert (1).

Maar omdat die overgeërfde members als Overridable staat gedefinieerd, kunnen we ook dit gedrag aanpassen in afgeleide klassen. De Student klasse bijvoorbeeld die van de Person klasse deze Overridable ToString() overerft, kan deze function overschrijven of dus koppelen aan een andere implementatie (2).
Visual Basic Broncode
Class Person
    Public Sub New(ByVal name As String)
        Me.Name = name
    End Sub
    Private m_Name As String
    Public Property Name() As String
        Get
            Name = m_Name
        End Get
        Set(ByVal value As String)
            m_Name = value
        End Set
    End Property
End Class
Class Student : Inherits Person
    Public Sub New(ByVal name As String, ByVal classGroup As String)
        MyBase.New(name)
        Me.ClassGroup = classGroup
    End Sub
    Private m_ClassGroup As String
    Public Property ClassGroup() As String
        Get
            ClassGroup = m_ClassGroup
        End Get
        Set(ByVal value As String)
            m_ClassGroup = value
        End Set
    End Property
    Public Overrides Function ToString() As String                         ' (2)
        ToString = Name & " (" & ClassGroup & ")"
    End Function
End Class
Module Example5
    Public Sub Main()
        Dim person1 As Person = New Person("John")
        Console.WriteLine(person1.ToString())                              ' (1)
        '
        Dim student1 As Student = New Student("Jane", "Visual Basic")
        Console.WriteLine(student1.ToString())                             ' (2)
        '
        Console.ReadLine()
    End Sub
End Module
Visual Basic Output
(*).Person
Jane (Visual Basic)
(*) Hier staat de na(a)m(en) van de namespace(s) waarin de klasse Person is gedefinieerd.

9.13.4. MyBase

Regelmatig komt het voor dat je in een herdefinitie het te herdefiniëren gedrag eerder wil uitbreiden dan vervangen.

De mogelijkheid bestaat in de implementatie van een herdefiniërende/overschrijvende member ( Overrides member ) de te herdefiniëren/overschrijven member ( Overridable member ) aan te roepen. Men kan dit door het MyBase keyword te laten voorafgaan aan de identifier van de te herdefiniëren/overschrijven member.
Visual Basic Broncode
Partial Class Counter
    Public Overrides Function ToString() As String
        ToString = Value.ToString()
    End Function
End Class
Partial Class SpecialCounter
    Public Overrides Function ToString() As String
        ToString = MyBase.ToString() & " - Step : " & StepValue.ToString() ' (1)
    End Function
End Class
Module Example6
    Sub Main()
        Dim counter1 As Counter = New Counter
        Console.WriteLine(counter1.ToString())
        '
        Dim specialCounter1 As SpecialCounter = New SpecialCounter
        Console.WriteLine(specialCounter1.ToString())
        '
        Console.ReadLine()
    End Sub
End Module
Visual Basic Output
0
0 - Step : 1
De ToString() implementatie van SpecialCounter herbruikt hier nu de ToString() van Counter (1) ( MyBase.ToString() ), en breidt het resultaat ervan uit om tot zijn eigen resultaat te komen.

We hadden hetzelfde resultaat kunnen bekomen door regel (1) te vervangen door :
ToString = Value.ToString() & " - Step : " & StepValue.ToString()

Hierbij wordt echter de ToString() van de basis klasse niet herbruikt, maar eerder gekopieerd. Een wijziging aan de ToString() van Counter zal dan geen effect hebben naar het resultaat van een ToString() op een SpecialCounter object.

Welke werkwijze te verkiezen valt, hangt af van de vereisten.

9.13.5. Oefeningen

Opgave 1 :

Zorg dat we objecten voor "employees" kunnen creëren. Een employee heeft een bepaald maandloon en een jaarloon ( dat 12 keer het maandloon is )

Zorg er ook voor dat we objecten voor "managers" kunnen creëren. Een manager is een employee, met eigenschappen maandloon, premie en jaarloon.
Het jaarloon van een manager wordt net zo berekend als van een gewone employee, met als verschil dat daar nog de premie wordt bij opgeteld.
Oplossing 1 :
Visual Basic Broncode
Class Employee
    Private m_MonthlySalary As Decimal
    Public Property MonthlySalary() As Decimal
        Get
            MonthlySalary = m_MonthlySalary
        End Get
        Set(ByVal value As Decimal)
            m_MonthlySalary = value
        End Set
    End Property
    Public Overridable Function GetYearlySalary() As Decimal
        GetYearlySalary = MonthlySalary * 12
    End Function
End Class
Class Manager : Inherits Employee
    Private m_Bonus As Decimal
    Public Property Bonus() As Decimal
        Get
            Bonus = m_Bonus
        End Get
        Set(ByVal value As Decimal)
            m_Bonus = value
        End Set
    End Property
    Public Overrides Function GetYearlySalary() As Decimal
        GetYearlySalary = MyBase.GetYearlySalary() + Bonus
    End Function
End Class
Module Exercise1Solution
    Public Sub Main()
        Dim employee1 As Employee = New Employee
        employee1.MonthlySalary = 1000
        Console.WriteLine(employee1.GetYearlySalary())
        '
        Dim manager1 As Manager = New Manager
        manager1.MonthlySalary = 2000
        manager1.Bonus = 10000
        Console.WriteLine(manager1.GetYearlySalary())
        '
        Console.ReadLine()
    End Sub
End Module
Visual Basic Output
12000
34000
Opgave 2 :
Creëer de nodige klasse om met onderstaande clientcode onderstaand programmaverloop te bekomen.
Visual Basic Broncode
Module Exercise2Task
    Sub Main()
        Dim addition1 As Addition = New Addition(3, 4)
        Console.WriteLine(addition1.GetSum())
        Console.WriteLine(addition1.ToString())
        '
        addition1.Operand1 = 5
        addition1.Operand2 = 6
        Console.WriteLine(addition1.GetSum())
        Console.WriteLine(addition1.ToString())
        '
        Console.ReadLine()
    End Sub
End Module
Visual Basic Output
7
3 + 4 = 7
11
5 + 6 = 11
Oplossing 2 :
Visual Basic Broncode
Class Addition
    Public Sub New(ByVal operand1 As Integer, ByVal operand2 As Integer)
        Me.Operand1 = operand1
        Me.Operand2 = operand2
    End Sub
    Private m_Operand1 As Integer
    Public Property Operand1() As Integer
        Get
            Operand1 = m_Operand1
        End Get
        Set(ByVal value As Integer)
            m_Operand1 = value
        End Set
    End Property
    Private m_Operand2 As Integer
    Public Property Operand2() As Integer
        Get
            Operand2 = m_Operand2
        End Get
        Set(ByVal value As Integer)
            m_Operand2 = value
        End Set
    End Property
    Public Function GetSum() As Integer
        GetSum = Operand1 + Operand2
    End Function
    Public Overrides Function ToString() As String
        ToString = Operand1 & " + " & Operand2 & " = " & GetSum()
    End Function
End Class
Opgave 3 :
Creëer de nodige klassen om met onderstaande clientcode onderstaande programmaverloop te bekomen.
Visual Basic Broncode
Module Exercise3Task
    Sub Main()
        Dim airport1 As Airport = New Airport("ZAV", "Brussels")
        Dim airport2 As Airport = New Airport("NYK", "New York Kennedy")
        '
        Dim flight1 As Flight = New Flight(airport1, airport2)
        Dim flight2 As Flight = New Flight(airport2, airport1)
        '
        Dim holiday1 As Holiday = New Holiday
        holiday1.Add(flight1)
        holiday1.Add(flight2)
        '
        For index As Integer = 0 To holiday1.Count - 1
            Console.WriteLine(holiday1.Item(index).ToString())
        Next
        '
        Console.ReadLine()
    End Sub
End Module
Visual Basic Output
ZAV : Brussels -> NYK : New York Kennedy
NYK : New York Kennedy -> ZAV : Brussels
Oplossing 3 :
Visual Basic Broncode
Class Holiday
    Private m_Items As Flight()
    Private m_Count As Integer
    Public ReadOnly Property Count() As Integer
        Get
            Count = m_Count
        End Get
    End Property
    Public Sub Add(ByVal flight As Flight)
        ReDim Preserve m_Items(Count)
        m_Items(Count) = flight
        m_Count += 1
    End Sub
    Default Public ReadOnly Property Item(ByVal index As Integer) As Flight
        Get
            Item = m_Items(index)
        End Get
    End Property
End Class
Class Flight
    Public Sub New(ByVal departure As Airport, ByVal arrival As Airport)
        Me.Departure = departure
        Me.Arrival = arrival
    End Sub
    Private m_Departure As Airport
    Public Property Departure() As Airport
        Get
            Departure = m_Departure
        End Get
        Set(ByVal value As Airport)
            m_Departure = value
        End Set
    End Property
    Private m_Arrival As Airport
    Public Property Arrival() As Airport
        Get
            Arrival = m_Arrival
        End Get
        Set(ByVal value As Airport)
            m_Arrival = value
        End Set
    End Property
    Public Overrides Function ToString() As String
        ToString = Departure.ToString() & " -> " & Arrival.ToString()
    End Function
End Class
Class Airport
    Public Sub New(ByVal code As String, ByVal Name As String)
        Me.Code = code
        Me.Name = Name
    End Sub
    Private m_Code As String
    Public Property Code() As String
        Get
            Code = m_Code
        End Get
        Set(ByVal value As String)
            m_Code = value
        End Set
    End Property
    Private m_Name As String
    Public Property Name() As String
        Get
            Name = m_Name
        End Get
        Set(ByVal value As String)
            m_Name = value
        End Set
    End Property
    Public Overrides Function ToString() As String
        ToString = Code & " : " & Name
    End Function
End Class

Dit artikel is gepubliceerd op woensdag 28 april 2010 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.

Visual Basic 2008 & 2010 Boeken

Het Groene Visual Basic 2008 & 2010 Voorbeelden Boek Het Blauwe Visual Basic 2008 & 2010 Voorbeelden Boek Het Rode Visual Basic 2008 & 2010 Voorbeelden Boek

Bevalt een artikel je, dan kan je de inhoud van vbvoorbeelden ook reclamevrij in boekvorm verkrijgen.

De inhoud is verdeeld over 3 boeken, Het Groene, Het Blauwe en Het Rode Visual Basic 2008 & 2010 Voorbeelden Boek.

Klik hier voor meer informatie.

Berichten

Fast UML Sequence Diagram Editor