I have a base class and a child class and they both have the same property and I don't understand why VB wants me to use "Overloads" for the property in the child class. The difference is the child class version of the property is Shared while the parent class is basically there for structure. The properties look like this:
Public MustInherit Class Parent
Public ReadOnly Property Species As String
Get
Return "Should get species from a child."
End Get
End Property
End Class
Public Class Child
Inherits Parent
Public Shared ReadOnly Property Species As String
Get
Return "Species1"
End Get
End Property
End Class
Species is flagged in the line Public Shared ReadOnly Property Species As String in the child class with the warning message
property 'Species' shadows an overloadable member declared in the base
class 'Parent'. If you want to overload the base method, this method
must be declared 'Overloads'.
What I want to know is why does it want this to be overloaded? Overloading is typically used when different parameters are being passed into functions with the same name which is well documented, but I've found nothing explaining why overloads is suddenly suggested in a situation like this.
Note: that the code properly reports "Species1" regardless of if have the "Overloads" or not adding to my confusion of what it actually does...
If you want to overload the base method, this method must be declared 'Overloads'.
The error message is too generic. Note how it talks about a method even though the warning is about a property. You cannot overload a property.
If I were the King of France, I would have written the error message like:
Property 'Species' hides the 'Species' property inherited from the 'Parent' base class. Use the Shadows keyword to suppress this warning if hiding was intended. Change the name of the property if hiding was not intended.
This warning should almost never be ignored because is almost always identifies a code smell. Using the Shared keyword for Child.Species is very strange and almost certainly not what you intended. Any code that uses your Child object through a reference of type Parent will always get the wrong species name since it will use the base property. The more sane thing to do here is to declare the Parent.Species property Overridable and use the Overrides keyword in Child.Species property declaration, without Shared.
If you shadow a member - the base class will still use it's version of the member when called. For example, if a function in your base class called Species it would still get the value "Should get species from a child."
In this case, overloading will cause functions in the base class to use the child's value.
To make this a bit clearer... the following code's message box says "Original Value", not "New Value"
Public Class Form1
Dim X As New Child
Dim Y = MsgBox(X.ShowMe)
End Class
Public Class Parent
Public Function ShowMe() As String
Return member
End Function
Public Property member As String = "Original value"
End Class
Public Class Child
Inherits Parent
Public Property member As String = "New value"
End Class
Related
Question:
In the below code, The O/P of Me.testShadow() when d.UseMe() gets executed, in my opinion should be "Shadowing Procedure: From the Derived Class". But instead the O/P that I am getting is "From Base Class: Shadowing procedure in derived class". I present my understanding as to why I think that the former should be output. PLease tell me where I am going wrong.
d is the derived class type reference pointing to an object of derived type.
d.UseMe() executes the statement Me.testShadow() inside it. ME behaves like an object variable pointing to the current instance, that is the object pointed to by "d". Therefore the reference that ME has is of derived class type.
testShadow() has two versions, one in the base class and the shadowing version in the derived class.
Since SHADOWS works on reference and since the type of ME reference is derived class type, I was expecting that the shadowing function in the derived class would be called? Instead, the testShadow() in the base class is being called.
Where am I mistaken? The code I wrote is given below:
Module Module1
Sub Main()
Dim b As New base()
Dim d As New derived()
d.useMe()
Console.ReadLine()
End Sub
End Module
Public Class base
Public Overridable Function testOverride() As String
Return "Overrideable function: From the base Class"
End Function
Public Function testShadow() As String
Return "From Base class. Shadowing function in inherited class"
End Function
Public Sub useMe()
Console.WriteLine("Me.testOverride() returns: {0}", Me.testOverride())
Console.WriteLine("Me.testShadow() returns: {0}", Me.testShadow)
End Sub
End Class
Public Class derived : Inherits base
Public Overrides Function testOverride() As String
Return "Overriden procedure: From derived class"
End Function
Public Shadows Function testShadow() As String
Return "Shadowing procedure: From derived class"
End Function
End Class
Overriding follows the type of the object, while shadowing follows the type of the reference. That useMe method is in the base class and Me will always be the type of the class it's used in, so Me is the base type. That means that Me.testShadow will execute the method in the base class.
You can easily prove to yourself that Me is type base by considering the fact that it is in a base class that could be inherited in any number of derived types. How could the type of the Me reference change depending on the derived type on which you called that method? References don't change type at run time. They are always whatever type they were when the code was compiled. That useMe method was written in the base class so it is type base and will always be that type.
So to start this off; I'm a beginner in VisualBasic.Net and my classes require me to learn it. The current subject is object constructors and constructor methods. The current exercise (it's not graded or an exam) is requiring us to make a parent class with a constructor method, and a child class with a new() that calls said function. It looks a bit like this;
Protected MustInherit Class Vehicle()
Protected ReadOnly Property Serial_No As Integer
Protected Property Mileage As Integer
Protected Property Color As String
Protected Function CreateVehicle() As Object
End Function
End Class
Public Class Car
Inherits Vehicle
Public ReadOnly Property Car_Type As String
Public Sub New()
End Sub
End Class
The thing I'm having issues with is that I'm not sure how to go about it? Can't ReadOnly properties ONLY be edited in the constructor itself, and doesn't the object need to be initialized in the constructor? Is there something particular I need to add in the CreateVehicle function?
I did ask the teacher but his answer was 'just give up on it and go do something else', which is ultimately pretty unhelpful.
Edit: (added the inheritance to the child class)
So, after being asked for clarification on what I'm trying to do; the exercise itself is not entirely about doing this, but it is the thing in the exercise that I'm struggling with. The goal is to create a Car object utilizing the constructor (New()), but the constructor must call a secondary function located inside the parent class, Vehicle.
My issue is the following : I'm not sure how to go about implementing the function inside the constructor. I know how to call methods/subs/functions and how to get returns from them, but I'm not sure on how I would go about returning a ReadOnly property's values from a secondary function. Don't readonly properties become uneditable outside of the constructor?
I could always return each value separately instead of as an object, and then set the Car object's values to be equal to the return of the function, individually. But then what's the point of calling a separate function instead of just passing everything as a parameter and doing it directly in the constructor?
This is probably what your teacher is looking for:
Public MustInherit Class Vehicle
Protected ReadOnly Property Serial_No As Integer
Protected Sub New(serialNumber As Integer)
Me.Serial_No = serialNumber
End Sub
End Class
Public Class Car
Inherits Vehicle
Public ReadOnly Property Car_Type As String
Public Sub New(serialNumber As Integer, carType As String)
MyBase.New(serialNumber)
Me.Car_Type = carType
End Sub
End Class
Both constructors take in parameters so the ReadOnly properties can be set.
I'm trying to access a shared property of a class passed as a parameter to a type-parametrised procedure. The reason why I'm doing this is so I can embed the various API call endpoints (among other class-specific things) as properties within the class itself. I've read some similar SO posts but nothing is close enough to be sure that it isn’t possible (which I think is likely).
Below is the essence of the structure - there's some pseudo code towards the end:
MustInherit Class BaseClass
Shared Property Endpoint As String
End Class
Class Person
Inherits BaseClass
Property Age As Integer
Property Name As String
Sub New()
_Endpoint = "/GetPerson"
End Sub
End Class
Class Event
Inherits BaseClass
Property When As Date
Property Type As String
Sub New()
_Endpoint = "/GetEvent"
End Sub
End Class
Function Retrieve(T As BaseClass)(Id As String) As T
Dim oResp As HttpResponse = MakeGetCall(T.Endpoint, Id) <- T.Endpoint throws a compile error
Return Deserialize(Of T)(oResp.Content)
End Function
Dim oPerson As Person = Retrieve(Of Person)("123")
Dim oEvent As Event = Retrieve(Of Event)("123")
To my tiny mind, I would have thought that, since T’s base class is BaseClass which contains the property Endpoint, I’d be ok. But seemingly not.
I've tried a fair few things from here on SO and other places to overcome this to no avail. Yes, I realize I could perform some kind of endpoint look-up based on the type of T but the above represents a very clean solution and I’d like to get it to work if possible.
Any ideas?
Assuming you want EndPoint to be different for each subclass, you should use MustOverride instead of Shared...
MustInherit Class BaseClass
Public MustOverride Property EndPoint As String
End Class
Then return a constant in each subclass
Class Person
Inherits BaseClass
Public Overrides Property EndPoint As String
Get
Return "/Person"
End Get
You might want to declare EndPoint as ReadOnly too.
The small limitation is that you'll need an instance of the class to access EndPoint (since it isn't Shared). If you have a parameterless constructor, you could use (New Person).EndPoint where needed.
In my VB.Net code, I know that when I declare a property in a class I can do so using the shorthand of, for example, Public Property Prop1 As String and .Net automatically creates a private variable _Prop1 that I can refer to within my class.
I also know that I can refer to that variable within my code using either _Prop1 or by Prop1.
Now since I've always assumed that the preferred method is to use the private variable, I've always tried to make modifications / write code within my class referring to _Prop1. This is where my problem now comes in...
I have the following situation:
Public Class MyClass_Base
Public Overridable Property Prop1 As String = "val1"
Public Sub Test()
If _Prop1 = ....
End Sub
End Class
Public Class MyClass
Inherits MyClass_Base
Public Overrides Property Prop1 As String = "val2"
End Class
Basically, I define the property as Overridable in my base class, now when I get to the Test() subroutine, _Prop1 has the value of Nothing. However Prop1 has the correct value of val2.
Programming gurus out there, what is the correct way to deal with this situation?
Do I ignore the auto-created prive variable _Prop1 and work with the public Prop1 or is there something else I should add in / not even use the shorthand notation for this and write my own getter / setter logic to ensure things change as I would like?
Thanks!!!
I think you've answered your own question. You should absolutely not rely on hidden compiler mechanics in your own code. You're referencing a variable that you did not declare and there is no guarantee in the framework that this variable will be there (or work as you might expect, as you've discovered) - it's a hack to use it, so don't.
Unless you have a very good reason not to, code in the class should reference the public property just the same as code using the class would. If you're using automatic properties then there is no difference between doing that and using the private variable. It also has the benefit that if you do, at a later time, decide to implement explicit getters and setters that your code does not break and that your new getters and setters get called.
To explore the reason you get the unexpected result, in declaring
Public Overrides Property Prop1 As String = "val2"
You end up with two different _Prop1 variables - MyClass_Base._Prop1 and MyClass._Prop1. When you then call Test(), you are calling the base class method and that will refer to the base class's _Prop1 variable which has not been set to anything since you have overriden the implicit variable, getter, and setter in the subclass.
To illustrate the point, this is similar to :
Public Class MyClass_Base
Private _Prop1 As String = "val1"
Public Sub Test()
Console.WriteLine(_Prop1)
End Sub
End Class
Public Class MySubClass
Inherits MyClass_Base
Private _Prop1 As String = "val2"
End Class
Sub Main()
Dim class1 As New MyClass_Base
Dim class2 As New MySubClass
class1.Test()
class2.Test()
End Sub
Where your output will be :
val1
val1
In the above case MyClass_Base._Prop1 is always initialized, however, while in your case, it is not. In either case, the Test() method belongs to the base class so it will always refer to its own _Prop1 and not any variables of the same name declared in subclasses.
If you do need to refer to the private field, for whatever reason, you have to be very careful about how you do it (and the implications that follow). Any method that does so would need to itself be Overridable if subclasses are intended to work with their own private variables in the same way. Not to suggest that you should continue to use implicit variables, but to demonstrate :
Public Class MyClass_Base
Public Overridable Property Prop1 As String = "val1"
Public Overridable Sub Test()
Console.WriteLine(_Prop1)
End Sub
End Class
Public Class MySubClass
Inherits MyClass_Base
Public Overrides Property Prop1 As String = "val2"
Public Overrides Sub Test()
Console.WriteLine(_Prop1)
End Sub
End Class
Here we get the "expected" result because MySubClass overrides test to reference its own private field. Better to just stick to using the property names.
From the documentation on Auto Implemented Properties:
"Attributes specified for the property do not apply to the backing field."
This is one of those areas where C# and VB.NET need to be aligned.
C# (correctly) does not allow you to access the auto implemented property backing field (without some convoluted work). I honestly don't know what you can access this in VB.
So the rule here is even though you can access the backing field of an auto implemented property you really shouldn't modify this directly (nor should you need to)
If you need to then you should use a defined backing field (with initialisation) and explicit Get and Set
I've noticed that a class can "overload" a read-only property of its parent class, even though this isn't allowed within a class. I don't understand why this is allowed or what (if anything) it accomplishes.
Class myClass
ReadOnly Property SomeProp As Integer
Get
Return 50
End Get
End Property
End Class
Class mySubClass
Inherits myClass
Overloads ReadOnly Property SomeProp As Integer
Get
Return 12
End Get
End Property
End Class
The signature of mySubClass.SomeProp is identical to myClass.Prop—how can the former overload the latter?
In practice this seems to function just like Shadows, is that true?
In essence yes, with the overload you'll have myClass::SomeProp and mySubClass::SomeProp
Given an instance of mySubClass, calls to SomeProp will resolve to mySubClass::SomeProp as the best match. However since it's Overloads and not Shadows, something like
Readonly Property SomeProp(x as Integer) as integer)
Get
Return 13
End Get
End Property
won't compile since it lacks the Overloads decorator.