Overload variables in VB.NET
The overload function is very normal, but sometimes it needs overload variables, such as the following example.
Class Person
Public Name As String
END CLASS
Class Orgnization
Public Head As Person
...
END CLASS
Orgnization is a class that represents an organization, which has a Head member that represents the leader of this organization, which is a Person type.
Now I want to derive a class School from ORGNIZation, and use it has defined a functional function, but I am not satisfied with the Person type, because it's too little, only one name, I want to add an AGE field, then I What should I do?
In C , this is a very simple matter, just design the Orgnization into a template class, but in VB, this is a big problem - because I actually need to overload the HEAD variable.
In vb.net introduces Delegate, and hides Shadows Concept, if they combine them with the overload function, you can achieve the overload of the variable, the idea is like this:
1. Delegate makes the function can be passed to another function as a parameter;
2, the function is returned, and can be overloaded, if I let a variable always be pointed out by a function, then reload this function, you can overload this variable, but there is One premise, that is, the variable that needs to be overloaded must be declared as an Object type or other base class type (if you can determine the derived type of this base class type);
3, hide the base class variable that needs to be overloaded by shadows, and then define a derived variable of the same name in the derived class (type is a derived type of the type of variable being overloaded);
4. In the base class, all variables to be retrieved are not directly referred to, but reference a delegate type function pointing to it;
5. In the derived class, the function of this delegate type is overloaded, which is changed to achieve overloading of the base class variable.
example:
Namespace P
Public Class Person
Public Name As String
END CLASS
Public class orgnization 'base class
Public head as new person 'Head needs to be overloaded
Protected delegate function f_head () as Person
Protected Overridable Function GetHead () AS Person 'Key: This function always points to the head class of Head,
And can be overloaded
Return HEAD
END FUNCTION
Public Sub Displayhead ()
MsgBox (). Name.toString ()) 'Indirect calls Head variable
There is a must pay attention to where getHead must bring parentheses.
If you don't want to be awkward, it is very simple - designing gethead into
Attributes
End Sub
'...
END CLASS
Public class schoolhead 'head will be overloaded into this type
Inherits Person
Public Age As Integer
END CLASS
Public Class School
Inherits OrgnizationPublic Shadows Head As New Schoolhead 'first hides the head of the base class with Shadows, then declare a new Head
Protected Overrides Function GetHead () AS Person 'Reserves this function and thus all the Head of the base class
Call, it turned out to be mapped to the base class GetHead
Function, now mapped to the derived class
function. And this function is to derived
HEAD variable, so that all functions of the base class
The call to the HEAD is all redirected to the derived
Type of HEAD
Return HEAD
END FUNCTION
'...
END CLASS
Now do code code to test:
Public SUB T
Dim p as new p.school
p.Head.name = "lj"
p.Head.Age = 100
p.displayhead ()
End Sub
The results showed that the LJ, indicating that the DisplayHead finally acts on the SHADOWS semantic description, and the total function of the base class is hidden on the base class, but here uses a small skill, implementation Redirection, enable the function of the base class to the members of the derived class.
From the perspective of the derived class, the heavy-duty Head does not cost too much code, just add a heavy-duty function, the key is that the base category should be designed - should have the old saying: the former people planted trees, the future generations
This example illustrates the most basic idea of overloading variables, but it also has obvious shortcomings:
1. GetHead () of the derived class is the Person type, not the Schoolhead type, and thus call this function each time in the derived class function, you must also use CType to convert it, it is very inconvenient. But if you think that the HEAD variable of this derived class will not be inherited, you can use the getHead function, but it is directly using the Head of the class. But if you think that the HEAD of this derived class is likely to be overloaded, there is no way to convert. For frequent use, of course, a private function (or attribute) can be designed, use it to package CType, and return to the Schoolhead type, and in other derived class functions, use this private function to turn one, this can be Write code easily;
2, if the base class has a public property head (of course, it may be a function), it passes the HEAD object, which is a bit trouble, because the derived class requires the instance of the Schoolhead type. This also has a way to resolve: Use a shadows to hide the public property of the base class, and design a HEAD property of the same name, in the GET segment, you can write this:
Return HEAD
If there are other useful code in the base class, you can add a few words in front: Head = mybase.head ...
3. Although this method is functional, it is necessary to turn several functions per call (whether it is inside or outside, or outside), the program performance is obviously affected, so if it is not special It is not necessary to do so, it is better to stick to it.
4, serialization problem. In this example, if serialization is serialized for School, it will be found to resolve the problem when declaring the serializer, but as long as the Head member in the base class Orgnization is declared as protected to protected. In fact, it is not only this application, as long as you use shadows to hide the base variable, and this base class variable is a PUBLIC type, this error will appear. I guess the reason: Although the base class variable is hidden, it does not exist, in fact it is still in memory, but the serializer does not find this problem, it only knows the public variables to detect the public variables. As a result, there were two variables of the same name, so I didn't know what to do, only an error. However, just declare this variable as private or protected, it is also a shortcomings. Further:
What if you want to overload an array?
There is no problem, the idea is the same.
Now some of the above examples have been modified:
Public class Orgnization '
Public head (1) as person 'Head is changed to array
Protected delegate function f_head () as person () 'Note: It is very strange, Person does not bring parentheses.
You can also run through!!
Protected overridable readonly property gethead () as person () 'Return Value change to array type
Get
Return HEAD
END GET
End Property
Public function displayhead ()
MsgBox (0) .Name.toString ()) 'Here is a different write method, and the properties are better.
END FUNCTION
Sub new ()
Head (0) = New Person 'Don't forget to create an instance
Head (1) = New Person
End Sub
'...
END CLASS
Calibrate the students below:
Public Class School
Inherits Orgnization
Public Shadows Head (1) as schoolhead 'also declares as an array
Protected Overrides Readonly Property GetHead () As Person () '
Get
Return HEAD
END GET
End Property
'...
Sub new ()
Head (0) = new schoolhead 'is still the same
HEAD (1) = new schoolheadhead
End Sub
END CLASS
Test code:
Sub T
DIM P as new school
HEAD (0) .Name = "lj"
HEAD (0) .age = 100
Displayhead ()
MSGBOX ("OK")
End Sub
The result is correct, display "LJ", explaining the array of DISPLAYHEADs or calls, not base classes.