Inheriting properties without inheritance - vb.net

I've got a strange question here, and I suppose the answer is no, but... is there any way of inheriting a class' prooperties without inheriting it, just by composition?
What I got now is something like this:
Public Class Mixer
Inherits SomeOtherClass
Private _motor As Motor
Public Property Active() As Boolean
Get
Return _motor.Active
End Get
Set(ByVal value As Boolean)
_motor.Active = value
End Set
End Property
Public Property Frecuency() As Boolean
Get
Return _motor.Frecuency
End Get
Set(ByVal value As Boolean)
_motor.Frecuency = value
End Set
End Property
'More properties and functions from Mixer class, not from Motor
'
'
End Class
So I need the class Mixer to show publicly all it's Motor properties, but I don't want to inherit Motor since I it already inherits from SomeOtherClass. Is there any faster, cleaner and easier way of doing this?
Thanks!
Edit:
Just for clarifying: I know I could use an interface, but since the implementation of Motor is the same for all classes, I would like to inherit its properties directly, without having to implement them again in each class that has a Motor... but without inheriting Motor.

I believe you can use properties within an interface and then implement that interface.
Have a look at this question

You could always make your private _motor a public property then you'd be able to get to the Motor properties indirectly. I know it's not quite what you are asking for.

The most widely accepted solution (if not the only solution) is to extract a common interface that is implemented in every class that wraps an instance of Motor.
Public Interface IMotor
Property Active As Boolean
Property Frequency As Boolean
End Interface
Public Class Motor
Implements IMotor
Public Property Active As Boolean Implements IMotor.Active
Public Property Frequency As Boolean Implements IMotor.Frequency
End Class
Public Class Mixer
Inherits SomeOtherClass
Implements IMotor
Private _motor As Motor
Public Property Active() As Boolean Implements IMotor.Active
Get
Return _motor.Active
End Get
Set(ByVal value As Boolean)
_motor.Active = value
End Set
End Property
Public Property Frequency() As Boolean Implements IMotor.Frequency
Get
Return _motor.Frequency
End Get
Set(ByVal value As Boolean)
_motor.Frequency = value
End Set
End Property
End Class

Related

Force multiple classes to have a specific shared member

I'm already searching for hours, but I cannot find any solution or even a possible way, that fits.
I need a way to enforce, that multiple classes have a shared member. This classes can not be inherits another class, because they are entity data model classes and i work on a partial class file beside the autogenerated files.
I tried to use an interface, but interfaces does not provide the option to declare a member as shared.
My try was like:
Public Interface IInterfaceA
ReadOnly Property PropA as String
End Interface
Public Partial Class ClassA
Implements IInterfaceA
Public Shared ReadOnly Property SPropA As String
Get
Return "FixedValueStringForClassA"
End Get
End Property
Public ReadOnly Property PropA As String Implements IInterfaceA.PropA
Get
Return SPropA
End Get
End Property
End Class
Public Partial Class ClassB
Implements IInterfaceA
Public Shared ReadOnly Property SPropA As String
Get
Return "FixedValueStringForClassB"
End Get
End Property
Public ReadOnly Property PropA As String Implements IInterfaceA.PropA
Get
Return SPropA
End Get
End Property
End Class
So I can call the PropA Member, when I get e.g. an array of types, that implements IInterfaceA.
But my first implementation does not enforce the shared property, only the normal property. To call the normal property, I would need an instance of that type, but this is not the way I searching for.
Maybe there is another solution to this problem.
Unfortunately you can't force a class to implement a shared member.
However, you CAN share extension methods from a module.
I had a similar problem recently with needing to share functions with multiple classes but still be able to run them as that class. Which I solved using extension methods.
Basically how it works is the module extends all objects that implement an interface, which can be conveniently included with the module, that interface will include anything the module will need access to from the calling class and the module will include anything that needs to be shared between all classes
Public Module SharedProp
Dim PropA As String
<Extension()>
Public Function GetPropA(Of T As IInterfaceA)(this As T) As String
Return PropA
End Function
<Extension()>
Public Sub SetPropA(Of T As IInterfaceA)(this As T, value As String)
PropA = value
End Function
Public Interface IInterfaceA
Property PropA As String
End Interface
End Module
so long as the module is included, any class which impliments your interface will have access to the module's extension methods, which in turn has access to the module's implicitly shared members
Imports SharedProp
Public Partial Class ClassA
Implements IInterfaceA
Public Property PropA As String Implements IInterfaceA.PropA
Get
Return Me.GetPropA()
End Get
Set(value As String)
Me.SetPropA(value)
End Set
End Property
End Class
Public Partial Class ClassB
Implements IInterfaceA
Public Property PropA As String Implements IInterfaceA.PropA
Get
Return Me.GetPropA()
End Get
Set(value As String)
Me.SetPropA(value)
End Set
End Property
End Class
Hope that helps solve your problem!
EDIT: Shared on Class basis instead of Interface
Public Module SharedProp
Dim PropA As Dictionary(Of Type, String)
<Extension()>
Public Function GetPropA(Of T As IInterfaceA)(this As T) As String
If PropA.ContainsKey(GetType(T)) Then
Return PropA(T)
Else
Return Nothing
End Function
<Extension()>
Public Sub SetPropA(Of T As IInterfaceA)(this As T, value As String) As String
If PropA.ContainsKey(GetType(T) Then
PropA(T) = value
Else
PropA.Add(GetType(T), value)
End If
End Function
Public Interface IInterfaceA
Property PropA As String
End Interface
End Module

Call baseclass property

It's rather a simple question and both will work. But I'm just wondering what the best practice is. When a child class changes a variable in the baseclass. Should it call the property or just change the underlying variable.
I'm not using the property to do something with the data. The code in the child class is the same. But what is considered the best practice OOP wise?
Sample code:
Public Class TestDirect
Protected temp As Integer
End Class
Public Class TestChldDirect
Inherits TestDirect
Public Sub New()
MyBase.temp = 1
End Sub
End Class
versus
Public Class TestProperty
Private _temp As Integer
'
Public Property temp() As Integer
Get
Return Me._temp
End Get
Set(ByVal value As Integer)
Me._temp = value
End Set
End Property
End Class
Public Class TestChldProperty
Inherits TestProperty
Public Sub New()
MyBase.temp = 1
End Sub
End Class
The second approach gives you more flexibility later on and better protects/hides your underlying implementation. For instance, in your example you might want to modify the type of temp, add some validation etc. Those changes would be more difficult in your first example as you would be affecting the classes that derive from your base class. In the second example you can make the change without affecting any derived classes.

Is there a keyword that can make a class variable readonly from outside the class but not on the inside?

Basically, the readonly keyword doesn't let me modify a field after I first create the class instance. I could use a property but in this case its just extra overhead. Is there a keyword to make a class field readonly from only outside the class?
make the field private, provide getter and setter for it.
Make the setter private.
This way the value can be seen from outside the class by the getter,but, cannot be set/written from outside the class.
this makes the property read-only from outside the class.
As others have stated, use a property. If you don't want to split the property into one Getter and one Setter then make the setter private.
Public Class Foo
Public Property Abc() As Object
Get
Return Me.m_Abc
End Get
Private Set(value As Object)
Me.m_Abc = value
End Set
End Property
Private m_Abc As Object
End Class
However: The common way is to set the access level of the field to Friend making it accessible within the same assembly, but not from outside the assembly.
Public Class Foo
Public ReadOnly Property Abc() As Object
Get
Return Me.m_Abc
End Get
End Property
Friend m_Abc As Object
End Class
No there isn't. This type is scenario is precisely why properties are provided in the first place. You get a whole lot of flexibility.
However, if you insist you want to use a read only field, you can use reflection to change the value:-
Public Class TestClass
Public ReadOnly MyNumber As Integer
Public Sub New()
'Readonly fields can only be changed this way
'in the constructor
Me.MyNumber = 900
End Sub
Public Sub ChangeNumber(ByVal num As Integer)
SetNumber(num)
End Sub
Private Sub SetNumber(ByVal num As Integer)
Dim fi = Me.GetType.GetField("MyNumber")
'Reflection can change the value of
'a read only field after construction
fi.SetValue(Me, num)
End Sub
End Class
Note that this is a very terrible thing. Reflection shouldn't be used for this sort of thing as you're going to take a performance hit. Just use properties and save yourself the trouble.

VB.Net Create Database table from class property

I'm trying to create an inheritable class(OF t) in vb.net that I will pass it a class of objects. Inside the class of objects I want to use the class properties to create a corresponding database table. Like below
Public Class SampleClass
#Region "Properties"
Private newPropertyValue As String
Public Property NewProperty() As String
Get
Return newPropertyValue
End Get
Set(ByVal value As String)
newPropertyValue = value
End Set
End Property
#End Region
Public Sub New()
End Sub
End Class
I'm new to vb.net so I don't know my way around exactly.
I was looking into class attributes for this action but they do not fully make sense to me yet. Thanks in advance.
You will want to get well versed on something called Code First. This should get you started.

Optional Readonly Property in VB.Net Interface

I am trying to develop a simple interface for allowing quick lists to be generated from classes. Basically, the interface needs to return an ID and a Name. However, some classes have a calculated name property which is read only, others just use a read/write name property. Basically, all I care is that it has a getter, it does not matter if the property has a setter. How can I write this interface to handle either or without throwing compile errors?
I have read this question and didn't really follow it, maybe I am just dense. If so, please show me the error of my ways :)
Looks like the answer from the other question will work: here's a sample:
Public Interface IReadOnly
ReadOnly Property Name() As String
End Interface
Public Interface IReadWrite
Inherits IReadOnly
Overloads Property Name() As String
End Interface
Public Class ReadOnlyClass
Implements IReadOnly
Private _Name
Public ReadOnly Property Name() As String Implements IReadOnly.Name
Get
Return _Name
End Get
End Property
End Class
Public Class ReadWriteClass
Implements IReadWrite
Private ReadOnly Property ReadOnly_Name() As String Implements IReadOnly.Name
Get
Return Name
End Get
End Property
Private _Name As String
Public Overloads Property Name() As String Implements IReadWrite.Name
Get
Return _Name
End Get
Set(ByVal value As String)
_Name = value
End Set
End Property
End Class
The above approach will actually result in classes that implement IReadWrite also implementing IReadOnly--so you'll actually need to downcast to IReadWrite in order to set the property.
Another approach, which avoids that issue but requires a little more logic in the implementing classes and their caller's is something like:
Public Interface ISometimesWritable
Property Name() As String
ReadOnly Property AllowNameEdit() As Boolean
End Interface
Public Class ReadOnlyClass
Implements ISometimesWritable
Public ReadOnly Property AllowNameEdit() As Boolean Implements ISometimesWritable.AllowNameEdit
Get
Return False
End Get
End Property
Private _Name As String
Public Property Name() As String Implements ISometimesWritable.Name
Get
Return _Name
End Get
Set(ByVal value As String)
Throw New NotSupportedException("Name cannot be set when AllowNameEdit is False")
End Set
End Property
End Class
Public Class ReadWriteClass
Implements ISometimesWritable
Public ReadOnly Property AllowNameEdit() As Boolean Implements ISometimesWritable.AllowNameEdit
Get
Return True
End Get
End Property
Private _Name As String
Public Property Name() As String Implements ISometimesWritable.Name
Get
Return _Name
End Get
Set(ByVal value As String)
_Name = value
End Set
End Property
End Class
Update: To answer the question about downcasting; "downcasting" is a term used to describe casting an object from a superclass, interface, or abstract base class Type into a more concrete Type.
For example, the first example above defines two interfaces: IReadOnly and IReadWrite. You'll notice that IReadWrite implements IReadOnly, which means that you can make both IReadWrite and IReadOnly calls to objects which implement IReadWrite.
Since IReadWrite implements IReadOnly, IReadWrite is said to be a "sub-class" of IReadOnly (although "sub-class" is more accurately used to describe a class which inherits a base class, rather then implements an interface--for the sake of simplicity they are very nearly the same concept). If IReadWrite is a sub-class of IReadOnly, then the inverse is true--IReadOnly is a super-class of IReadWrite.
For example, I can describe an instance of ReadWriteClass as an implementation of either interface:
Public Sub SomeMethod()
dim readOnlyInstance as IReadOnly = new ReadWriteClass()
Console.WriteLine(readOnlyInstance.Name)
' The following line won't compile, since we're communicating with ReadWriteClass as an instance of IReadOnly
'readOnlyInstance.Name = "Santa Clause"
' Here we downcast the variable to reference it by it's other interface, IReadWrite
dim readWriteInstance = DirectCast(readOnlyInstance, IReadWrite)
' Now we can both Get and Set the value of Name
readWriteInstance.Name = "John Doe"
Console.WriteLine(readWriteInstance.Name)
' Note that in the above example we created *one* instance of ReadWriteClass
' and have provided two variables / references to the same underlying object.
Console.WriteLine(readOnlyInstance.Name) ' <-- note that this should return "John Doe"
End Sub