0

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.

Community
  • 1
  • 1
Paul
  • 463
  • 1
  • 4
  • 13
  • 2
    I would not call a class `Char` as it is a reserved word – Michael Jul 02 '13 at 15:04
  • "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." You have to copy and paste the variable declaration into every class anyways. Plus, if the property is ReadOnly then does it really need the private variable behind it? Why not just return the appropriate String for each sub-type? – Idle_Mind Jul 02 '13 at 15:22
  • @Idle_Mind, it's more that I would like the code to be shorter and easier to read. If possible, it would be nice to have every child class have one line per property/variable set. NoAlias's solution works below and if it takes 5 lines per property per character type, 5 lines per property per character type is what I'll have to use, but if I can condense it, I'd love to. – Paul Jul 03 '13 at 00:46

2 Answers2

3

You can make the BaseClass Species Property Overridable to achieve what you're looking for.

Public MustInherit Class [Char]

    Private _ID As Integer
    Private _Species As String

    Public Overridable ReadOnly Property Species As String
        Get
            Return _Species
        End Get
    End Property

End Class

Public Class CharCat
    Inherits Char

    Public OverLoads Shared 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
NoAlias
  • 9,218
  • 2
  • 27
  • 46
  • This works, but it'll make my code SUPER LONG to have to list 10 getters for each property of the 100+ character types. Do you know if there's a way to do this more concisely? – Paul Jul 02 '13 at 23:27
  • Also, can you explain why the "Overloads" is required? It doesn't seem to follow the standard overloaded method convention of having unique parameters so why does it work, and why is it needed? – Paul Jul 03 '13 at 15:20
  • You'll have to grind out all those getters. Usering MustOverride Class / Properties in the CharClass may make it easier for you, since when you inherit from one VS will automatically generate the property for you. Overloads should've been Overrides and I have updated my answer. – NoAlias Jul 03 '13 at 15:29
  • You can't use "Overrides" and "Shared" for the same property... "Overloads" works and raises no warning flags, but it just doesn't make sense to me... – Paul Jul 03 '13 at 15:55
1

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.

Community
  • 1
  • 1
Paul
  • 463
  • 1
  • 4
  • 13