Я не совсем ясен относительно того, почему или когда использовать Интерфейсы. Может кто-то отправлять полный, простой и небольшой пример Интерфейса с помощью VB.NET в Консольном приложении. Как это расширяемо?
Рассмотрим этот простой интерфейс:
Public Interface IWeightedValue
Public ReadOnly Property Weight As Double
Public ReadOnly Property Value As Double
End Interface
Даже не написав больше кода, я могу начать работать с этой концепцией в других частях своего кода. Например:
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
И вуаля - теперь для любого класса, который я пишу, если я просто заставлю его реализовать IWeightedValue
, тогда я смогу вычислить средневзвешенное значение для коллекции экземпляров этого класса .
Вкратце: предпочтение композиции перед наследованием
Интерфейсы - это просто общий набор определений членов, которые вы хотите, чтобы поддерживал один или несколько классов. Ключевым моментом является то, что при реализации интерфейса вы должны предоставить функциональность в явном виде.
Вы можете достичь аналогичных результатов, используя наследование, поскольку два подкласса могут наследовать полнофункциональные члены от базового. Но недостатком наследования является то, что ваши подклассы оказываются в жесткой зависимости от базового класса.
Рассмотрим следующие классы:
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
Можно сказать, что эти два класса в некоторой степени связаны между собой, поскольку у них обоих есть метод OpenDoor(). У вас может возникнуть желание даже создать базовый класс для извлечения общей функциональности.
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
Затем вы могли бы использовать эту абстракцию следующим образом:
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
Однако связывать дом с автомобилем только на основании того факта, что вы можете получить доступ к ним с помощью ключа, - довольно слабая абстракция. Черт возьми, даже банку с фасолью можно открыть!
Но есть и другие точки, где также может возникнуть связь. Например, и в машине, и в доме может быть кондиционер:
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
Должна ли функция TurnOnAirConditioning() быть извлечена и в базовый класс? Какое отношение это имеет к тому, чтобы быть OpenableProperty? Может ли класс JewelrySafe наследоваться от OpenableProperty без кондиционера? Лучший ответ в этой ситуации - извлечь интерфейсы и использовать их для компоновки функциональности в наших классах, а не для наследования:
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
Тогда ваши абстракции можно использовать следующим образом:
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
SecurityService можно использовать для проверки Car, House и JewelrySafe, а ThermostatService можно использовать только для проверки AC в Car и 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
Что должно дать следующие результаты:
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!