VB if base class implements interface, does the derived class also need to implement? - vb.net

I was analyzing a code. There we have a base class (not abstract) implementing an interface. Then we have a derived class of the base class which also implements the interface.
Interface:
Public Interface MainInterface
Function getMetaThreads(ByVal ThreadCount As Integer) As String()
Property Name() As String
Property TargetDirectory() As String
Property TimeOut() As Long
ReadOnly Property ExecutableAssembly() As String
ReadOnly Property IsVersionValid() As Boolean
End Interface
Base class:
Public Class BaseClass
Implements MainInterface
Public Sub print()
Console.WriteLine("BaseClass printing")
End Sub
Public ReadOnly Property ExecutableAssembly As String Implements MainInterface.ExecutableAssembly
...
End Property
Public ReadOnly Property IsVersionValid As Boolean Implements MainInterface.IsVersionValid
...
End Property
Protected strName As String = ""
Protected strTargetDirectory As String = ""
Protected lngTimeout As Long = 0
Public Property Name As String Implements MainInterface.Name
...
End Property
Public Property TargetDirectory As String Implements MainInterface.TargetDirectory
...
End Property
Public Property TimeOut As Long Implements MainInterface.TimeOut
...
End Property
Public Function getMetaThreads(ThreadCount As Integer) As String() Implements MainInterface.getMetaThreads
...
End Function
Public Overridable Function myOwnFunc() As String
Return ""
End Function
End Class
Derived Class:
Public Class SubClass
Inherits BaseClass
Implements MainInterface
Public Function getMetaThreads(ThreadCount As Integer) As String() Implements MainInterface.getMetaThreads
Return myOwnFunc()
End Function
Overrides Function myOwnFunc() As String()
Dim l As New List (Of String)
l.Add("44")
l.Add("33")
return l.ToArray()
End Function
End Class
Does it make sense to implement the interface in the derived class again? Is there a reason or a case where this becomes necessary? I think that having the base class implement the interface should be enough and implementing it in the interface is redundant.

Related

CodeAccessSecurityAttribute derived class throwing System.TypeLoadException (Failure has occurred while loading a type)

I have custom attribute applied to CRUD repository methods to control access:
Public Class SecureDbContextGenericRepository(Of TEntity As Class, TContext As DbContext)
Inherits DbContextGenericRepository(Of TEntity, TContext)
Public Sub New(connectionService As IConnectionService)
MyBase.New(connectionService)
End Sub
<EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataWriter)>
Public Overrides Sub Delete(ParamArray entities() As TEntity)
MyBase.Delete(entities)
End Sub
<EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataWriter)>
Public Overrides Sub Insert(ParamArray entities() As TEntity)
MyBase.Insert(entities)
End Sub
<EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataReader)>
Public Overrides Function [Select](Optional predicate As Func(Of TEntity, Boolean) = Nothing) As IList(Of TEntity)
Return MyBase.Select(predicate)
End Function
<EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataWriter)>
Public Overrides Sub Update(ParamArray entities() As TEntity)
MyBase.Update(entities)
End Sub
End Class
This is implementation of attribute:
Public Class EmployeeRoleRequirementAttribute
Inherits CodeAccessSecurityAttribute
Public Sub New(action As SecurityAction)
MyBase.New(action)
End Sub
Public Overrides Function CreatePermission() As IPermission
Return New EmployeeRolePermission(_EmployeeRoles)
End Function
Public Property EmployeeRoles As EmployeeRoles
End Class
<Flags>
Public Enum EmployeeRoles As Integer
DataReader = 0
DataWriter = 1
End Enum
And permission:
Public Class EmployeeRolePermission
Implements IPermission
Public Sub New(employeeRoles As EmployeeRoles)
_EmployeeRoles = employeeRoles
End Sub
Public Function Copy() As IPermission Implements IPermission.Copy
Return New EmployeeRolePermission(_EmployeeRoles)
End Function
Public Sub Demand() Implements IPermission.Demand
Dim principal = DirectCast(Thread.CurrentPrincipal, ProductionAssistantPrincipal)
If Not principal.IsInRole(_EmployeeRoles) Then
Throw New SecurityException(String.Format(My.Resources.EmployeeRoleNotFound,
principal.Identity.Name,
_EmployeeRoles.ToString()))
End If
End Sub
Public Sub FromXml(e As SecurityElement) Implements ISecurityEncodable.FromXml
Throw New NotImplementedException()
End Sub
Public Function Intersect(target As IPermission) As IPermission Implements IPermission.Intersect
Return New EmployeeRolePermission(_EmployeeRoles And DirectCast(target, EmployeeRolePermission).EmployeeRoles)
End Function
Public Function IsSubsetOf(target As IPermission) As Boolean Implements IPermission.IsSubsetOf
Return _EmployeeRoles.HasFlag(DirectCast(target, EmployeeRolePermission).EmployeeRoles)
End Function
Public Function ToXml() As SecurityElement Implements ISecurityEncodable.ToXml
Throw New NotImplementedException()
End Function
Public Function Union(target As IPermission) As IPermission Implements IPermission.Union
Return New EmployeeRolePermission(_EmployeeRoles Or DirectCast(target, EmployeeRolePermission).EmployeeRoles)
End Function
Public ReadOnly Property EmployeeRoles As EmployeeRoles
End Class
Every time one of the CRUD methods are reached, TypeLoadException is thrown. I really dont know cause of this, but if I remove attributes from CRUD methods, everything works fine.
This seems to be due to the enum-valued property on the attribute (see https://connect.microsoft.com/VisualStudio/feedback/details/596251/custom-cas-attributes-with-an-enum-property-set-cause-a-typeloadexception for details). To work around this issue, you could use a string-valued property on the attribute and cast to an enum either in the property setter or just before creating the permission. (Personally, I'd probably opt for the former in the interests of enabling early validation, but ymmv...)
Another workaround is making attribute property of type, which is used in Enum, in this case Integer.
Public Class EmployeeRoleRequirementAttribute
Inherits CodeAccessSecurityAttribute
Public Sub New(action As SecurityAction)
MyBase.New(action)
End Sub
Public Overrides Function CreatePermission() As IPermission
Return New EmployeeRolePermission(CType(_RequiredEmployeeRoles, EmployeeRoles))
End Function
Public Property RequiredEmployeeRoles As Integer
End Class
<Flags>
Public Enum EmployeeRoles As Integer
DataReader = 0
DataWriter = 1
End Enum
Then you dont need to use String, which does not allow easy combining of flags when attribute is used:
<EmployeeRoleRequirement(SecurityAction.Demand, RequiredEmployeeRoles:=EmployeeRoles.DataReader Or EmployeeRoles.DataWriter)>
Sub SecuredMethod()
End Sub

Interfaces & Sub-classes with different types

I have the following situation, that I'm pretty sure can be solved through the use of interfaces, but am not quite experienced enough to implement and keep losing myself.
Public Class IPGateway
Property Hostname As String
Property Port As Integer
Public Function Read()
Return OtherClass.Read(Hostname, Port)
End Sub
End Class
Public Class SerialGateway
Property Port As String
Property Baud As Integer
Public Sub Read()
Return YetAnotherClass.Read(Port, Baud)
End Sub
End Class
Public Sub Main()
Dim GatewayList as New List(of Gateways?) <- Interface here?
GatewayList.Add(SerialGateway)
GatewayList.Add(IPGateway)
For each gateway in GatewayList
Console.Write(gateway.Hostname() OR gateway.Baud)
Console.Write(gateway.Read())
Next
End Sub
I would welcome advice on how to best implement this approach?
You have 2 choises, one with Abstract Classes (MustInherit for VB) and one with interfaces. You have to decide which one works best for you!
Module Module1
Sub Main()
Console.WriteLine("With Abstract Classes")
Dim GatewayList As New List(Of TheBase)
GatewayList.Add(New SerialGateway With {.Baud = 5, .Port = "10"})
GatewayList.Add(New IPGateway With {.Hostname = "Test", .Port = "15"})
For Each gateway In GatewayList
Console.WriteLine(gateway.Port)
If TypeOf gateway Is SerialGateway Then
Console.WriteLine(DirectCast(gateway, SerialGateway).Baud)
ElseIf TypeOf gateway Is IPGateway Then
Console.WriteLine(DirectCast(gateway, IPGateway).Hostname)
End If
Console.WriteLine(gateway.Read())
Next
Console.WriteLine("With Interface")
Dim GatewayList2 As New List(Of TestIn)
GatewayList2.Add(New SerialGateway2 With {.Baud = "5", .Port = "10"})
GatewayList2.Add(New IPGateway2 With {.Hostname = "Test", .Port = "15"})
For Each gateway As TestIn In GatewayList2
Console.WriteLine(gateway.Port)
Console.WriteLine(gateway.Property2)
Console.WriteLine(gateway.Read())
Next
Console.ReadLine()
End Sub
End Module
Public Class IPGateway
Inherits TheBase
Property Hostname As String
Public Overrides Function Read() As String
Return "IPGateway"
End Function
End Class
Public Class SerialGateway
Inherits TheBase
Property Baud As Integer
Public Overrides Function Read() As String
Return "SerialGateway"
End Function
End Class
Public MustInherit Class TheBase
Public Property Port As String
Public MustOverride Function Read() As String
End Class
Public Interface TestIn
Property Port As String
Property Property2 As String
Function Read() As String
End Interface
Public Class SerialGateway2
Implements TestIn
Public Property Port As String Implements TestIn.Port
Public Property Baud As String Implements TestIn.Property2
Public Function Read() As String Implements TestIn.Read
Return "SerialGateway2"
End Function
End Class
Public Class IPGateway2
Implements TestIn
Public Property Port As String Implements TestIn.Port
Public Property Hostname As String Implements TestIn.Property2
Public Function Read() As String Implements TestIn.Read
Return "IPGateway2"
End Function
End Class

Access property of class not declared by interface

How can I access a property of a class which is not declared in the interface it implements?
Interface IMyInterface
Property MyInterfaceProperty As String
End Interface
Public Class MyImplementingClass
Implements IMyInterface
Public Property MyClassProperty As String
Public Property MyInterfaceProperty As String Implements IMyInterface.MyInterfaceProperty
End Class
Public Class MyTestClass
Public Sub New()
Dim foo As IMyInterface = New MyImplementingClass
foo.MyInterfaceProperty = "foo"
foo.MyClassProperty = "bar" '### Compile Error MyClassProperty is not a member of IMyInterface
End Sub
End Class
I've tried adding
foo = CType(foo, MyImplementingClass)
but it doesn't work...

VB generics with constraints -- type casting and inheritance?

Take this scenario:
Public Interface IMyClass
End Interface
Public mustinherit class MyBaseClass : implements IMyClass
End Class
public class MyClass : inherits MyBaseClass
End Class
public class MyModel(of t as IMyClass)
private Dim _parameter as t
Public Sub New(byval parameter As t)
_parameter As t
End Sub
End class
In my controller, I can do this with no problem:
Dim _myclass as IMyClass = new MyClass()
Can I do something similar with this:
Dim _myModel as MyModel(of IMyClass) = new MyModel(of MyClass)
???
My initial thought was wrong, as I thought the conversion could be done automatically, but it appears it is not done. Any way to achieve the same thing within .NET?
EDIT
I updated the MyModel class to show more of what I was doing. I want to constrain the instance I create, but then do what would be a narrowing conversion with traditional, non-generics code. Basically, my partial Razor views would require the explicit model, and those views end up rendering another view that will take that model and display it. Because the models all implement or inherit a class that implements IMyClass, all the methods should exist on all of the instances and should be callable but the types are not interchangable.
Let’s modify MyModel slightly, shall we?
Public Class MyModel(Of T As IMyClass)
Private _parameter As T
Public Sub Something(parameter As T)
_parameter = parameter
End Sub
End class
Public Class MyClassA : Inherits MyBaseClass
End Class
Public Class MyClassB : Inherits MyBaseClass
End Class
Dim _myModel As MyModel(Of IMyClass) = New MyModel(Of MyClassA)()
_myModel.Something(New MyClassB()) ' Boom!
If the assignment were allowed the last line would pose a problem: MyMode(Of MyClassA)._parameter has type MyClassA but the last line would assign an object of the (unrelated) type MyClassB. This is illegal and so VB forbids it.
Do you need multiple varieties of MyModel, or are you just attempting to require that the stored object be constrained to IMyClass?
Simplest approach (that might not do everything you need):
Public Interface IMyClass
Sub DoIt()
End Interface
Public Class MyModel
Private ReadOnly _parameter As IMyClass
Public Sub New(parameter As IMyClass)
_parameter = parameter
End Sub
Public Sub DoItToIt()
_parameter.DoIt()
End Sub
End Class
Public Class MyClassA
Implements IMyClass
Public Sub DoIt() Implements IMyClass.DoIt
End Sub
End Class
Public Class Tests
Public Sub Main()
Dim model1 As MyModel = New MyModel(New MyClassA)
model1.DoItToIt()
End Sub
End Class
Next step up in complexity is to define an interface IHasMyClass for classes that contain an IMyClass. This supports manipulations based on the allowed type, and the actual type, of the contained object:
Public Interface IMyClass
Sub DoIt()
End Interface
Public Interface IHasMyClass
Function GetIt() As IMyClass
Function GetItsType() As Type
Function GetAllowedType() As Type
End Interface
Public Class MyModel(Of T As IMyClass)
Implements IHasMyClass
Private ReadOnly _parameter As IMyClass
Public Sub New(parameter As IMyClass)
_parameter = parameter
End Sub
Public Sub DoItToIt()
_parameter.DoIt()
End Sub
Public Function GetItAsT() As T
Return _parameter
End Function
Public Function GetIt() As IMyClass Implements IHasMyClass.GetIt
Return _parameter
End Function
Public Function GetItsType() As Type Implements IHasMyClass.GetItsType
Return _parameter.GetType()
End Function
Public Function GetAllowedType() As Type Implements IHasMyClass.GetAllowedType
Return GetType(T)
End Function
End Class
Public Class MyClassA
Implements IMyClass
Public Sub DoIt() Implements IMyClass.DoIt
End Sub
End Class
Public Class Tests
Public Sub Main()
' Allow any IMyClass
Dim model1 As MyModel(Of IMyClass) = New MyModel(Of IMyClass)(New MyClassA)
model1.DoItToIt()
Dim it As IMyClass = model1.GetIt()
Dim allowedT As Type = model1.GetAllowedType()
' Restrict to MyClassA
Dim modelA As MyModel(Of MyClassA) = New MyModel(Of MyClassA)(New MyClassA)
modelA.DoItToIt()
Dim itA1 As IMyClass = modelA.GetIt()
Dim itA2 As MyClassA = modelA.GetItAsT()
Dim allowedTA As Type = modelA.GetAllowedType()
End Sub
End Class
In Tests(), notice that we now need to declare whether we are creating a MyModel that accepts ANY IMyClass MyModel(Of IMyClass), or one that requires a specific sub-class MyModel(Of MyClassA).
If we want to manipulate MyModels, that may be either of the above types, we use the common interface:
Dim model As IHasMyClass
model = model1
...
model = modelA
Or in your case, to support all the functionality of MyModel, rename IHasMyClass as IMyModel, and add the various MyModel functions, but instead of T, use IMyClass:
Public Interface IMyModel
Function GetIt() As IMyClass
Function GetItsType() As Type
Function GetAllowedType() As Type
Sub DoItToIt()
Function CompareIt(other As IMyClass) As Integer
End Interface
And make appropriate changes/additions to IMyClass and MyModel.
Then it becomes possible to do:
Dim model As IMyModel = modelA
If model.CompareIt(model1.GetIt()) > 0 ...

how to access class from inherited class

I have two classes:
class class2
inherits class1
public sub modify()
'modify property of class1
end sub
end class
How can I modify class1 in a sub in class2?
You just call it. Example:
Public Class class1
Private _Value As String = String.Empty
Property Value() As String
Get
Return _Value
End Get
Set(ByVal value As String)
_Value = value
End Set
End Property
End Class
Public Class class2
Inherits class1
Public Sub modify()
Value = "modified"
End Sub
End Class
And to show it works:
Dim c2 As New class2
c2.modify()
MessageBox.Show(c2.Value)
You are asking about properties, note that only protected and public properties are visible to inherited classes.
You need the MyBase keyword when you are overriding an existing function in the parent class. Other protected or public properties or functions can be accessed regulary without any special keyword.
One tip I wanted to add to the above comments regarding accessing base class info is where you have a base class without a default contructor or want to use a specific constructor This is a good opportunity to use Mybase. You have to call the constructor before any additional actions take place in this scenario.
Public Class MyClass
Inherits baseClass
Public Sub New()
mybase.new("Oranges")
End Sub
End Class
Public Class baseClass
Private _someVariable as String
Public Sub New(byval passedString as string)
_someVariable = passedString
End Sub
End Class