I'm throwing this problem out the community.
I would really like is a way of having methods that only exist on the base-class.
Token (The Base-Class)
A Descendant: Digit
OK. So on to the issue of the .Parse
Requirements
Since the way of creating a instance of any Derived Token is going be the same.
Strict Requirement:
Issues with what I've tried.
Which to me just feels so wrong, to me it should be in Token class.
So is there a way of define Base-Class only methods?
An Idea: Partial Inheritance.
A class can specify what aspect of it can be inherited.
Partial Inheritance
Only some of the traits of the parents are passed on the their children.
Deerived Class
I would really like is a way of having methods that only exist on the base-class.
Token (The Base-Class)
<ComponentModel.ImmutableObject(True)>
Public MustInherit Class Token
Private _Index As Integer
Private _Count As Integer
' Constructor is only visible from inside Token and it Descendants '
Protected Friend Sub New(ByVal Index As Integer, Count As Integer)
_Index = Index : _Count = Count
End Sub
Public ReadOnly Property Index As Integer
Get
Return _Index
End Get
End Property
Public ReadOnly Property Count As Integer
Get
Return _Count
End Get
End Property
' This parser is only visible from inside Token '
' Essentially a Factory Method, produce an Instance of a Digit (Token)
Protected Shared Function Parser(ByRef ParseState As ParseState) As ParseState
Return ParseState
End Function
End Class
A Descendant: Digit
Public Class Digit
Inherits Token
Private Sub New(ByVal Index As Integer, Count As Integer)
MyBase.New(Index, Count)
End Sub
Protected Overloads Shared Function Parser(ByRef cr As CharReader) As Digit
Dim crc = cr.Current
If crc.HasValue = False Then Return Nothing
Select Case crc.Value
Case "0"c To "9"c : Return New Digit(cr.Index, 1)
Case Else : Return Nothing
End Select
End Function
End Class
OK. So on to the issue of the .Parse
Requirements
- The only way to create a Token is via this a shared function on Token
So I can control how they are constructed.
Example
Dim dt = Token.Parse(Of Digit)(Reader)
so the following would an error.
Dim dt = Digit.Parse would be an error, since Parse doesn't exist at all on the class Digit. Note: Not just hidden from the the IDE and Intellisense, I really meaning that any Derived Class of Token doesn't that is non-existent.
Since the way of creating a instance of any Derived Token is going be the same.
Strict Requirement:
Issues with what I've tried.
- Use an Interface
Can't specify Shared Methods. - Composition
The Composed Class wouldn't be a Token, which it need to be it this design. - Inheritance
Sounds reasonable.
Public MustInherit Class Token ... Public Function Parse(Of T As Token)(ByRef cr As CharReader) As T Return Parser(cr) End Function ...
no the Issue is the Parse method appear on only descendants.
Sort of solve by doing.
Protected Shadows Function Parse(ByRef cr As CharReader) As Digit Return Digit.Parse(cr) End Function
now the Issue is how to access the shared method in the Derived Class?
Since the Parse are essentially the same
{ClassName}.Parse(cr)
Why not find a way directly invoke (call) that hidden parser method from the base?
Resorting to using Generics and Reflection
Public Shared Function Parse(Of T As Token)(ByRef cr As CharReader) As ParseState Dim start = cr.Index ' ' Here Be Nasty Reflection Based Bodge Job ' ' Why? What I want to write. ( Call a static method on the generic (constrianed) type specifier.) ' ' Return T.Parser(cr) ' ' Start Bodgery { Dim args As Object = {cr} Dim tt As T = GetType(T).InvokeMember("Parser", Reflection.BindingFlags.InvokeMethod + Reflection.BindingFlags.NonPublic + Reflection.BindingFlags.Static, Nothing, tt, args) cr = args(0) ' The ByRef Value get returned back into array. If tt Is Nothing Then cr = cr << start Return tt ' } End Bodgery End Function
This leaves the issue of remove the .Parse from descendants.
The only way I could find is extracting the parse code and placing it in Module.
Public Module TokenLIB Public Function Parse(Of T As Token)(ByRef cr As CharReader) As T Dim start = cr.Index ' ' Here Be Nasty Reflection Based Bodge Job ' ' Why? What I want to write. ( Call a static method on the generic (constrianed) type specifier.) ' ' Return T.Parser(cr) ' ' Start Bodgery { Dim args As Object = {cr} Dim tt As T = GetType(T).InvokeMember("Parser", Reflection.BindingFlags.InvokeMethod + Reflection.BindingFlags.NonPublic + Reflection.BindingFlags.Static, Nothing, tt, args) cr = args(0) ' The ByRef Value get returned back into array. If tt Is Nothing Then cr = cr << start Return tt ' } End Bodgery End Function
Which to me just feels so wrong, to me it should be in Token class.
So is there a way of define Base-Class only methods?
An Idea: Partial Inheritance.
A class can specify what aspect of it can be inherited.
Partial Inheritance
Only some of the traits of the parents are passed on the their children.
Public MustInherit Class Token
MustOverride Protected Shared Function Parser(cr As CharReader ) As Token
NonInheritible Public Function Parse(Of T As Token)(cr As CharReader) As T
Return (Of T).Parser(cr)
' Invoke a shared method on generic parameter type. '
End Function
End Class
Deerived Class
Public Class Digit Inherit Token Overrides Protected Shared Function Parser(cr As CharReader ) As Token End Function /* No Parse method exist for the child class */ End Class
3 Comments On This Entry
Page 1 of 1
cfoley
20 February 2012 - 05:56 AM
My inclination is that if you don't want something to be inherited, it shouldn't be in the base class. Since your method is shared, you could easily put it in a class or module of its own.
In Java, static (shared) methods aren't inherited. I'm not sure how this applies to VB but static methods belongs to their class, not the subclasses. In older versions of Java, calling Digit.Parser() would have given you an error, although I think later versions allow it as syntactic sugar.
I don't like the idea of NonInheritable. It has the huge drawback of encouraging poor design, and I can't see any positives.
In Java, static (shared) methods aren't inherited. I'm not sure how this applies to VB but static methods belongs to their class, not the subclasses. In older versions of Java, calling Digit.Parser() would have given you an error, although I think later versions allow it as syntactic sugar.
I don't like the idea of NonInheritable. It has the huge drawback of encouraging poor design, and I can't see any positives.
cfoley
20 February 2012 - 08:59 AM
Well, that's OK too. Make it non-overrideable (if it isn't by default) and then you know any invocation ends up at the right piece of code.
Why don't you make a separate factory class or module?
Why don't you make a separate factory class or module?
Page 1 of 1
|
|



3 Comments








|