Search code examples
vb.netclassshared

Declare Class Level Variables in Child Class


I would like to declare class level variables for a bunch of child classes similar to this in python: Static class variables in Python. I've learned that the shared attributed is probably what I want to use, but I'm not quite sure where to use it.

Here's my situation: I am making a bunch of different character types for a game (100+). All the character types have the same set of properties, so I've created a base class that includes all of the properties and the required internal variables. Each character type has a set of immutable properties that are exactly the same for every instance of the given character type, but differ between character types. I would like to contain the immutable character type properties as class "variables" in child classes (one child class per character type), like in the answer to the python example above.

The key is I would like to reference some properties WITHOUT having to create an instance of the sub class.

My problem is I can't figure out what needs to be shared to properly do this or how my code needs to be organized to make this happen. I tried sharing the properties which finally allowed me to get to the properties from the child class and not just an instance of the child, but then it wouldn't return the property I assigned in the child class using Shared or Shared Shadows. I would like to keep the properties in the base class so that I don't have to copy and paste the same properties for every child class.

Here is some samples of my code:

Public MustInherit Class Char

    'IMMUTABLE INFORMATION
    '  CharType Traits
    Shared _ID As Integer
    Shared _Species As String

    Public Shared ReadOnly Property Species As String
        Get
            Return _Species
        End Get
    End Property
End Class

Public Class CharCat
    Inherits Char

    Shared Shadows _Species = "Cat"
End Class

The goal is to be able to type CharCat.Species and have it return "Cat". I know this example is redundant with the class name, but for other properties it's not.


Solution

  • Using NoAlias's response as a spring board in collaboration with more research and SO questions, I've found an complete answer. The base class does NOT need Overridable considering that, since the child class uses Shared, it CAN'T have a Overrides property. Overloads reportedly does nothing to a property according to Hans Passant so we don't need that either.

    Now the code works with these two changes but there's a warning flag that says the property should be declared as "Overloads" which isn't actually the proper solution. To properly get rid of the warning, Shadows should be declared. The code worked without declaring shadows because Shadowing is the default behavior for a child property, but in order to get rid of the warning VB throws, you need to declare it explicitly.

    The code ends up looking like this:

    Public MustInherit Class [Char]
    
        Private _ID As Integer
        Private _Species As String
    
        Public ReadOnly Property Species As String
            Get
                Return _Species
            End Get
        End Property
    
    End Class
    
    Public Class CharCat
        Inherits Char
    
        Public Shared Shadows ReadOnly Property Species As String
            Get
                Return "Cat"
            End Get
        End Property
    
    End Class
    
    Private Sub Form1_Load(ByVal sender As System.Object, _ 
        ByVal e As System.EventArgs) Handles MyBase.Load
    
        MsgBox(CharCat.Species)
    
    End Sub
    

    It's important to note that we now have to deal with the Shadows behavior. If a child class is called through the parent class, you'll get parent class behavior for the property. For me, since I couldn't use Overrides because I'm using Shared, I decided the best way to avoid the parent class behavior was to just get ride of the parent class property since it wasn't holding any important information anyways. You could try be super careful not to call a child through the parent in your code to avoid the parent behavior as well.