views:

82

answers:

3

I have a couple of small classes to represent parts in a search filter. If the searched value equals NonValue the filter is supposed to do nothing. This is defined in a Base Class:

    Private Class BaseFilter
        Protected NonValue As Object
        Protected sQueryStringBase As String = "AND {0} {1} {2} "

        Public Sub CheckNonValue(ByVal QueryItem As Object)
            'No Query if Item not valid
            If Me.NonValue.Equals(Me.QueryItem) Then
                Me.sQueryStringBase = String.Empty
            End If
        End Sub

    End Class

BaseFilter is then extended for different types of fields:

    Private Class StringFilter
        Inherits BaseFilter
        Protected Shadows NonValue As String = String.Empty
    End Class

When I then create a StringFilter and check for allowed value:

Dim stf As New StringFilter()
stf.CheckNonValue(MyString)

I get a NullReferenceException (NonValue = Nothing) , when I expected the NonValue object to be String.Empty. Is this a bug in my code, or am I trying to achieve polymorphism in a wrong way? Thanks.

A: 

let the subclass pass the NonValue object to its base through constructor.

just somebody
This is what I ended up doing. But the base class seems still to test Equal() with Object.Equals(), which checks memory address. Therefore, I had to override the CheckNonValue() method in the subclasses and cast my NonValue into the desired type <code>CType(Me.NonValue, String)</code> before testing.
Jonas
A: 

Shadowing is the opposite of what you want... Shadowing in Visual Basic will allow two variables to be named the same thing but not refer to the same object (i.e. the signature is the same, but it means different things).

This happens automatically for example when you have a locally defined variable foo and a class level variable foo. Any calls to foo within the local scope will access the local variable and outside the scope it will access the class level variable.

Andrew Flanagan
@Andrew: There are more classes that inherits from BaseFilter, and the idea was to be able to reuse the CheckNonValue Method in the inheriting classes, since the idea is the same anyway.
Jonas
Yes, but I think that this can't be accomplished using shadowing -- you want to use something like what Serilla recommends.
Andrew Flanagan
You where right about shadowing, it was really overriding I was looking for.
Jonas
+1  A: 

I think what you are trying to achieve can be done by making NonValue Overridable in BaseFilter, then in your derived class...

Private Class StringFilter
   Inherits BaseFilter
   Protected Overrides NonValue As String = String.Empty
End Class

EDIT:

As you've rightly pointed out you can't override a member variable. Also, you can't override one type with another; so even if you had changed your member variables to properties, my original suggestion (above) would not have worked. To atone for my sins :) I have put together another suggestion, using generics:

Public MustInherit Class Filter(Of T)

    Protected NullValue As T
    Protected QueryStringBase As String = "AND {0} {1} {2} "

    Public Sub CheckNonValue(ByVal value As T)
        If NullValue.Equals(value) Then
            Me.QueryStringBase = String.Empty
        End If
    End Sub

End Class

Public Class StringFilter
    Inherits Filter(Of String)
    Public Sub New()
        NullValue = String.Empty
    End Sub
End Class

Public Class ObjectFilter
    Inherits Filter(Of Object)
    Public Sub New()
        NullValue = Nothing
    End Sub
End Class
JulianM
I wasn't able to set Members as Overridable (at least not in .NET 2.0, should perhaps have mentioned that).
Jonas
It is true that you cannot override member variables. In most circumstances you would use properties instead, but in your case I have had to edit my original answer to provide an altogether different solution.
JulianM