2010-05-05 14 views
6

Non sono abbastanza chiaro perché o quando utilizzare le interfacce. Qualcuno può pubblicare un esempio completo, semplice e piccolo di un'interfaccia usando VB.NET in un'applicazione console. Come è estensibile?Interfacce VB.NET

+2

possibile duplicato di http://stackoverflow.com/questions/1983962/how-do-interfaces-work-and-how-to-use-them-in-practical-programming –

+0

O di http: // stackoverflow. it/questions/122883/interfaces-why-cant-i-seem-to-grasp-them – Walter

+0

Suggerisco di leggere "Programming Components in .NET" di Juval Lowy; è un libro solido per spiegare molti concetti importanti diversi e le interfacce sono ben trattate. – STW

risposta

29

In breve: Favor Composizione per l'eredità

interfacce sono semplicemente un insieme comune di definizioni membro che si desidera una o più classi di supporto. La chiave è che devi fornire esplicitamente la funzionalità quando implementi un'interfaccia.

È possibile ottenere risultati simili utilizzando l'ereditarietà poiché due sottoclassi possono ereditare membri completamente funzionali dalla base. Ma il lato negativo dell'ereditarietà è che le sottoclassi finiscono per avere una forte dipendenza dalla classe base.

Considerate le seguenti classi:

Public Class Car 
    Publc Sub OpenDoor(ByVal key As MyKey) 
     Console.WriteLine("Access granted to car.") 
    End Sub 
End Class 

Public Class House 
    Public Sub OpenDoor(ByVal key as MyKey) 
     Console.WriteLine("Access granted to house.") 
    End Sub 
End Class 

Si potrebbe dire che queste due classi sono in qualche modo correlati perché entrambi hanno un metodo OpenDoor(). Potresti essere tentato persino di creare una classe base per estrarre funzionalità comuni.

Public Class OpenableProperty 
    Public Sub OpenDoor(ByVal key As MyKey) 
     Console.WriteLine("Access granted to property.") 
    End Sub 
End Class 

Public Class Car 
    Inherits OpenableProperty 
End Class 

Public Class House 
    Inherits OpenableProperty 
End Class 

È quindi possibile utilizzare questa astrazione come questo:

Public Class SecurityService 
    Public Sub InspectProperty(ByVal item As OpenableProperty) 
     Dim key As New MyKey() 
     Console.WriteLine("Inspecting property...") 
     item.OpenDoor(key) 
    End Sub 
End Class 

Tuttavia, in relazione una casa da una macchina basata esclusivamente sul fatto che è possibile accedervi con una chiave è un'astrazione piuttosto debole. Diamine, anche una lattina di fagioli può essere apribile!

Ma ci sono altri punti in cui potrebbe verificarsi anche una relazione. Ad esempio, sia una macchina e una casa potrebbe avere l'aria condizionata:

Public Class Car 
    Inherits OpenableProperty 
    Public Sub TurnOnAirConditioning() 
     Console.WriteLine("Cool breezes flowing in car!") 
    End Sub 
End Class 

Public Class House 
    Inherits OpenableProperty 
    Public Sub TurnOnAirConditioning() 
     Console.WriteLine("Cool breezes flowing in house!") 
    End Sub 
End Class 

Should TurnOnAirConditioning() essere estratti per la classe di base troppo? Che cosa ha a che fare con l'essere una proprietà aperta? Una classe JewelrySafe potrebbe ereditare da OpenableProperty senza un AC? La risposta migliore a questa situazione è quello di estrarre interfacce e utilizzare questi per comporre la funzionalità nelle nostre classi, piuttosto che ereditare:

Public Interface IOpenable 
    Sub OpenDoor(ByVal key As MyKey) 
End Interface 

Public Interface ICoolable 
    Sub TurnOnAirConditioning() 
End Interface 

Public Class Car 
    Implements IOpenable, ICoolable 
    Public Sub OpenDoor(ByVal key as MyKey) Implements IOpenable.OpenDoor() 
     Console.WriteLine("Access granted to car.") 
    End Sub 
    Public Sub TurnOnAirConditioning() Implements ICoolable.TurnOnAirConditioning() 
     Console.WriteLine("Cool breezes flowing in car!") 
    End Sub 
End Class 

Public Class House 
    Implements IOpenable, ICoolable 
    Public Sub OpenDoor(ByVal key as MyKey) Implements IOpenable.OpenDoor() 
     Console.WriteLine("Access granted to house.") 
    End Sub 
    Public Sub TurnOnAirConditioning() Implements ICoolable.TurnOnAirConditioning() 
     Console.WriteLine("Cool breezes flowing in house!") 
    End Sub 
End Class 

Public Class JewelrySafe 
    Implements IOpenable 
    Public Sub OpenDoor(ByVal key as MyKey) Implements IOpenable.OpenDoor() 
     Console.WriteLine("Access granted to jewelry safe.") 
    End Sub 
End Class 

Allora i vostri astrazioni possono essere consumati come tali:

Public Class SecurityService 
    Public Sub InspectProperty(ByVal item As IOpenable) 
     Dim key As New MyKey() 
     Console.WriteLine("Inspecting property...") 
     item.OpenDoor(key) 
    End Sub 
End Class 

Public Class ThermostatService 
    Public Sub TestAirConditioning(ByVal item as ICoolable) 
     Console.WriteLine("Testing Air Conditioning...") 
     item.TurnOnAirConditioning() 
    End Sub 
End Class 

Il poteva SecurityService quindi essere utilizzato per ispezionare la Car, House e JewelrySafe, mentre il ThermostatService potrebbe essere utilizzato solo per testare l'AC di Car and House.

Sub Main() 
    Dim securityService As New SecurityService() 
    Dim thermostatService As New ThermostatService() 

    Dim house As New House() 
    Dim car As New Car() 
    Dim jewelrySafe As New JewelrySafe() 

    With securityService 
     .InspectProperty(house) 
     .InspectProperty(car) 
     .InspectProperty(jewelrySafe) 
    End With 

    With thermostatService 
     .TestAirConditioning(house) 
     .TestAirConditioning(car) 
    End With 
End Sub 

Che dovrebbe produrre i seguenti risultati:

Inspecting property... 
Access granted to house. 
Inspecting property... 
Access granted to car. 
Inspecting property... 
Access granted to jewelry safe. 
Testing Air Conditioning... 
Cool breezes flowing in house! 
Testing Air Conditioning... 
Cool breezes flowing in car! 
+0

Un esempio * molto * bello, facile da capire e abbastanza ragionevole. Complimenti! Sei un insegnante o qualcuno? :) – pepoluan

+0

No, solo qualcun altro in trincea di tanto in tanto gli presta una mano. Penso che stavo leggendo alcuni libri di Head First quando ho scritto questo e alcuni dei loro stili sono stati cancellati! – Technobabble

+0

Ottima spiegazione dell'uso dell'implementazione rispetto all'ereditarietà. Un commento, rimuovere il() alla fine degli strumenti espliciti. Ad esempio, Implements IOpenable.OpenDoor() dovrebbe leggere Implements IOpenable.OpenDoor –

2

considerare questo semplice interfaccia:

Public Interface IWeightedValue 
    Public ReadOnly Property Weight As Double 
    Public ReadOnly Property Value As Double 
End Interface 

Senza nemmeno scrivere più codice, posso iniziare a trattare con questo concetto in altre parti del mio codice.Per esempio:

Public Function GetWeightedAverage(ByVal points As IEnumerable(Of IWeightedValue)) As Double 
    Dim totalWeight As Double = 0.0 
    Dim totalWeightedValue As Double = 0.0 

    For Each point As IWeightedValue in points 
     totalWeight += point.Weight 
     totalWeightedValue += (point.Weight * point.Value) 
    Next 

    Return totalWeightedValue/totalWeight 
End Function 

E voilà - ora per qualsiasi classe che scrivo, se ho appena rendono implementare IWeightedValue allora posso calcolare la media ponderata per una raccolta di istanze di questa classe.

+0

Mi sembra di capire quasi lo scopo delle interfacce, ma non è ancora stato ancora cliccato per me. Forse dovrei tornare a leggere di nuovo tra un paio di giorni. Lo farò +1 se mi dai un altro esempio o ti elabori in qualche modo. – Lopsided