Hi, currently the interface definition in .NET just allow define a set of method declaration template, and not allow includes any implentation details. But the java language it does, the interface define in java can includes some default method implentation, and I thinks this feature can introduce in the .NET language too.
Actually, the interface with default method implentation in java language can be simulated in .NET language by using extension method of the interface type or abstract class
For example, using the extension method for this simulation:
<Extension>
Public Function DefaultMethodExample(of T As InterfaceType)(x As T) As .....
' Overrides for a specifc interface implentation class
' Where T2 is a type which implement the interface InterfaceType
<Extension>
Public Function DefaultMethodExample(Of T As T2)(x As T) .......
Or using an abstract class is also works, but the problem is that the abstract class just not allow multiple inherits and the extension method is not so Convenient. So i think this java language feature can be introduce into VB/C#.
This default interface method is useful for some common operations of an interface type, and can save a lot of time from the duplicate coding for this job.
For example, in visualbasic define for the default interface method implementation in Interface with VB Default
keyword:
Public Interface IExample(Of T)
Default ReadOnly Property Value(key$) As String
Get
Dim s As New Value(Of String)
Return If("" = (s = GetData(key$)), s, Provider(NameOf(IExample(Of ).Provider & key$)).ToString)
End Get
End Property
Default Function GetData As NameValueCollection
Return New NameValueCollection
End Function
Function Provider As Dictionary(Of String, T)
End Interface
Were in this interface its implentation type, can overrides the default method with Overloads
keyword:
Public Class T2
Implements IExample(Of String)
Public Overloads Function GetData As NameValueCollection Implements IExample(Of String).GetData
' blablabla
End Function
Public Function Provider As Dictionary(Of String, String) Implements IExample(Of String).Provider
' blablabla
End Function
End Class
I don't see any benefit. If you like to provide a default, then why don't you provide an abstract class that implements the interface and that provides some partial implementation? In VB you can ship it together, the abstract class can be an inner class of the interface:
Public Interface ILockable
ReadOnly Property IsLocked As Boolean
Sub Lock()
MustInherit Class DefaultImplementation
Implements ILockable
Private _IsLocked As Boolean
Public ReadOnly Property IsLocked As Boolean Implements ILockable.IsLocked
Get
Return _IsLocked
End Get
End Property
Public Sub Lock() Implements ILockable.Lock
_IsLocked = True
End Sub
Protected Sub CheckLocked()
If (_IsLocked) Then Throw New InvalidOperationException("The instance is locked!")
End Sub
End Class
End Interface
Whether this is best practice or not I let up to you to decide. But it's quite elegant to be consumed:
Public Class LockableObject
Inherits ILockable.DefaultImplementation
Private _SomeValue As DateTime
Public Property SomeValue As DateTime
Get
Return _SomeValue
End Get
Set(value As DateTime)
CheckLocked()
_SomeValue = value
End Set
End Property
End Class
@HugoRoss From a C# perspective, extension methods are fantastic tools. This will not change. They are much more broadly applicable, if less conceptually pure, than default interface methods because they can augment any type and can do it transiently, i.e. when brought into scope by referencing an assembly and/or importing a namespace. However, the use case for default methods is to allow an imbued type to take part in the method selection process by providing its own implementation. They serve different purposes.
Hi , @HugoRoss,
In practice, using abstract class for the default method simulation just partly works:
The class can not multiple inheritance but the interface does, so if a class type implement 2 different interface and these 2 interface both have the default method implements, then the abstract class simulation failure to work
For example,
Interface I
Default Function a As String
Return "123"
End Function
End Interface
Class a : Implements I
Private Overloads Function bb As String Implements I.a
Return "123"
End Function
End Class
Class b : Implements I
Public Overloads Function a As String Implements I.a
Return "233"
End Function
End Class
Class c: Implements I
End Class
These function alias all works,
Call DirectCast(New a, I).a.Echo ' 123
Call DirectCast(New b, I).a.Echo ' 233
Call DirectCast(New c, I).a.Echo ' 123
The function overrides in class type Inheritance its signature must keeps the same, but the interface method implementation doesn't
MustInherits Class cc : Implements II
' All of the interface method is Public access, but we can change its implements function access
' But this situation is not allowed in the class inherits
Private Function a As String Implements II.Function_b
End Function
Protected MustOverrides Function b As String Implements II.a123
Public MustOverrides Function c As String Implements II.bbb
End Class
All of this access controls from the interface method are works perfectly in VisualBasic
NO!
Assume that we have a extension method using as the default method implements for an interface type in namespace a, and another extension method for implements as a default method for a specific interface implements type in namespace b
Namespace a
Public Module IDefault
' This method works for all type that implements interface I
<Extension> Public Sub DefaultExample(Of T As I)(x As T)
Namespace b
Public Module IDefault
' This method works for all type c2, and c2 Implements the interface I
<Extension> Public Sub DefaultExample(Of T As c2)(x As T)
For example, if we want using the default method in namespace b
, and we forget imports the namespace b
but imports the namespace a
, so that the function that we used for this default method implementation is the function in namespace a
, but the function in namespace a is totally differently with the function in namespace b
, this will easily makes bugs and makes you app malfunction.
@amethyst-asuka yes, this is the point!
@amethyst-asuka Indeed. I fully agree. However for extension methods
For example, if we want using the default method in namespace b, and we forget imports the namespace b but imports the namespace a, so that the function that we used for this default method implementation is the function in namespace a, but the function in namespace a is totally differently with the function in namespace b, this will easily makes bugs and makes you app malfunction.
this is actually a great thing.
Again they both serve different purposes.
Closing as a dup of #258
Hi , @amethyst-asuka,
Reply to "Abstract classes cannnot have multiple inheritance, aliases, change visibility and do not work with structures"
You are right, abstract classes are not that convenient (although they work, of course). Here an example with concrete classes (my new suggestion for handling these cases without adding new syntax to the language).
Interface I1
Function F1() As String 'has a default
Function F2() As String 'has no default
Class DefaultImplementation
Implements I1
Public Overridable Function F1() As String Implements I1.F1
Return "I1.F1()"
End Function
Public Overridable Function F2() As String Implements I1.F2
Throw New NotImplementedException()
End Function
End Class
End Interface
Interface I2
Function F1() As String 'has a default
Function F2() As String 'has no default
Class DefaultImplementation
Implements I2
Public Overridable Function F1() As String Implements I2.F1
Return "I2.F1()"
End Function
Public Overridable Function F2() As String Implements I2.F2
Throw New NotImplementedException()
End Function
End Class
End Interface
Structure A
Implements I1, I2
'Hint: Does not work for structs
'Private ReadOnly _I1Instance As New I1.DefaultImplementation()
'Private ReadOnly _I2Instance As New I2.DefaultImplementation()
Private _I1Instance As I1.DefaultImplementation
Private _I2Instance As I2.DefaultImplementation
Private ReadOnly Property I1Instance As I1.DefaultImplementation
Get
Dim myResult As I1.DefaultImplementation = _I1Instance
If (myResult Is Nothing) Then
myResult = New I1.DefaultImplementation()
_I1Instance = myResult
End If
Return myResult
End Get
End Property
Private ReadOnly Property I2Instance As I2.DefaultImplementation
Get
Dim myResult As I2.DefaultImplementation = _I2Instance
If (myResult Is Nothing) Then
myResult = New I2.DefaultImplementation()
_I2Instance = myResult
End If
Return myResult
End Get
End Property
Private ReadOnly Property P1 As String
Get
Return "P1"
End Get
End Property
Private Function F1() As String Implements I1.F1
Return I1Instance.F1() & "."c & P1
End Function
Public Function OtherF1() As String Implements I2.F1
Return I2Instance.F1() & "."c & P1
End Function
Friend Function F2() As String Implements I1.F2, I2.F2
Return "F()"
End Function
End Structure
This example shows a structure that uses default implementations of two different interfaces and changes the visibility of their methods.
(And alright, maybe a slight addition to VB syntax would simplify it...)
Most helpful comment
Hi , @HugoRoss,
In practice, using abstract class for the default method simulation just partly works:
The disadvantage of abstract class simulate interface default method
1. abstract class can not multiple inheritance
The class can not multiple inheritance but the interface does, so if a class type implement 2 different interface and these 2 interface both have the default method implements, then the abstract class simulation failure to work
2. interface have function alias name, but abstract class it doesn't
For example,
These function alias all works,
3. interface have function access control, but abstract class it doesn't
The function overrides in class type Inheritance its signature must keeps the same, but the interface method implementation doesn't
All of this access controls from the interface method are works perfectly in VisualBasic
3. abstract class can apply on Structure Type?
NO!
The disadvantage of extension method simulate interface default method
Assume that we have a extension method using as the default method implements for an interface type in namespace a, and another extension method for implements as a default method for a specific interface implements type in namespace b
For example, if we want using the default method in
namespace b
, and we forget imports thenamespace b
but imports thenamespace a
, so that the function that we used for this default method implementation is the function innamespace a
, but the function in namespace a is totally differently with the function innamespace b
, this will easily makes bugs and makes you app malfunction.16074
8127
60
258
73