Class Pointer

  • Thread starter Thread starter David A. Osborn
  • Start date Start date
D

David A. Osborn

I have a set of classes that each have an enumeration in them, and based on
dynamic input I need to access a different enumeration. For example

Three classes Class_A, Class_B, and Class_C that all have a different
enumeration in them called Properties. I want to basically have a variable
The_Class that I can dynamically point to either Class_A, Class_B, or
Class_C and then do The_Class.properties to get the correct enumeration.
How would I define the Class point variable and load it to the correct
class?
 
One way would be to put it in your New() method
and set a private internal property = to the parameter that was passed in.

For instance,

Private _PropSet as String

Public Sub New(PropSet as string)
_PropSet = PropSet
End Sub

Then you could use logic in the "Get" for your properties enum
to branch based on the value of _PropSet

I hope I understood you correctly.

GL
 
I don't think you understood the question, or I don't understand the answer.
Basically I need to make a generic pointer variable that I can point at
which ever class I want.
 
David A. Osborn said:
I have a set of classes that each have an enumeration in them, and based on
dynamic input I need to access a different enumeration. For example

Three classes Class_A, Class_B, and Class_C that all have a different
enumeration in them called Properties. I want to basically have a variable
The_Class that I can dynamically point to either Class_A, Class_B, or
Class_C and then do The_Class.properties to get the correct enumeration.
How would I define the Class point variable and load it to the correct
class?

Can you put that in context? What you are asking for is a late bound
approach to the Properties enumeration from each of the different classes.
But enumerations are just a friendly way of defining constants, (giving you
Intellisense) which you would loose when using The_Class in that late bound
fashion.

I am just thinking there might be a different way to go about doing what you
want to do, where a bigger picture would be needed to understand the
need for constants from different classes....

LFS
 
Basically I have a series of classes that represent items in my program.
These items all have different properties that need to be displayed in a
property window. When the property window geta focus it will check to se
what item is selected and dynamically build the label boxes on itself based
on what the item is. How I've organized this is each item is its own class.
In each class is an enumeration for that item which contains the properties
for that particular item. So the properties panel needs to decide what
class to use based on the string that is passed to it, and then loop through
the enumerations to dynamically build labels on itself?

I'm looking to do something like this. Obiviously this code/psuedo code,
but hopefully it will portray the idea:


Public Class Item_A_Class
Public Enum Properties
prop_1
prop_2
prop_3
End Enum

Some Funtions

End Class

Public Class Item_B_Class
Public Enum Properties
prop_A
prop_B
prop_C
prop_D
End Enum

Some Functions

End Class


Private Sub Build_Properties_Panel (ByVal Item As String)
If Item = "ItemA" then
Dim Dynamic_Class As Item_A_Class
If Item = "ItemB" then
Dim Dynamic_Class As Item_B_Class
EndIf
'Loop through enumeration for class
Dim properties as String() =
System.enum.GetNames(GetType(Dynamic_Class.properties))
For i As Integer = 0 to name.Length -1
do code to build label

Next

End Sub



My plan was that it the properties for ItemA or ItemB ever changed someone
would just write a new class that inherits the old one and change the
enumeration, and the display could would continue to work perfectly fine. I
suppose I could just do the above loop in each if statement specifically for
the class, but I thought the code would be more concise if I dynamically
pointed Dynamic_Class to which ever class it needed to be and then only had
one loop in the subroutine.

Thanks for the help!
 
Hummm ... not a workable design.
My plan was that it the properties for ItemA or ItemB ever changed someone
would just write a new class that inherits the old one and change the
enumeration,

When the new class inherits from the old class (i.e. Item_A_Class or
Item_B_Class class) it will inherit the enumeration Properties also.
However, the new class will not be able to override the enumeration. It
will only be able to shadow the enumeration. This means that you will have
to completely duplicate the enumeration in each derived class. This
completely defeats a crucial purpose of object orientated design; code
re-use.

An enumeration is not an effective type for storing a list of items. The
call to get the element names in the enumeration is very slow. Using the
element names as the data storage is not what an enumeration is designed
for. There are many other types that implement the IList interface that are
more efficient at storing and retrieving items in a list. Use one of these
instead.

The manner in which you want to use one variable type (Dynamic_Class) to
access methods in two different types (Item_A_Class and Item_B_Class) is
known as polymorphism in object oriented design. In order for you to
implement this with your Item_A_Class and Item_B_Class classes you need
something common to both of them that the Dynamic_Class class can use to
access them. Currently there is nothing common in both classes. You may
think that and enumeration named Properties is common to both but consider
this; the system sees the enumerations as Item_A_Class.Properties and
Item_B_Class.Properties, two completely different enumerations.

So, how do we apply polymorphism to these classes? There is a method that
is slow and prone to run-time error. Simply make Dynamic_Class of type
Object. The Object type is common to all types. Then use late-binding to
access the Properties enumeration. For example,

Dim Dynamic_Class As Object = New Item_A_Class()
Dim properties as String() = _
System.Enum.GetNames(GetType( _
Dynamic_Class.Properties))

As I said above this is a very messy approach as there is no design-time or
compile-time type checking. Therefore, it is very easy for you or another
programmer to make errors that can not be caught until the project is
complied and the particular section of code is run. Also, error checking
late bound errors is generally a hellish experience as the compiler is only
able offer limited support.

As you add more item classes with even more enumerations this code will
become slower and even more prone to late-bound errors.

Do not dispair, there is hope. "We can rebuild [it]. We have the
technology." (Six Million Dollar Man, 1970s)

Anyway ... in order to cleanly get what you ultimately are seeking we need
to redevelope your design to take advantage of inheritance so polymorphism
and hence early-binding and strong type-checking with design-time support
can be applied. First we need to decide on a type to hold your property
data. As stated above any one of the types that implement the IList
interface will suffice. Since we do not want consumers of these objects to
modify, delete or add property names we will use an ArrayList. Now we can
define a class ItemBase that has a protected ArrayList and a public read
only Properties property.

Public MustInherit Class ItemBase
Protected _propertyNames As ArrayList
Public ReadOnly Property Properties() As ArrayList
Get
Return ArrayList.ReadOnly(_propertyNames)
End Get
End Property
End Class

We will make the ItemBase type common to all item classes through
inheritance.

Public Class ItemA
Inherits ItemBase
Public Sub New()
Dim names As String() = {"prop_1", "prop_2", "prop_3"}
_propertyNames = New ArrayList(3)
_propertyNames.AddRange(names)
End Sub
End Class

Public Class ItemB
Inherits ItemBase
Public Sub New()
Dim names As String() = {"prop_A", "prop_B", "prop_C"}
_propertyNames = New ArrayList(3)
_propertyNames.AddRange(names)
End Sub
End Class

Now we can use an ItemBase variable to access the common Properties property
of any item class.

Private Sub BuildPropertiesPanel(ByVal Item As String)
Dim ibProperties As ItemBase
Select Case Item
Case "ItemA"
ibProperties = DirectCast(New ItemA(), _
ItemBase)
Case "ItemB"
ibProperties = DirectCast(New ItemB(), _
ItemBase)
Case Else
Throw New ArgumentOutOfRangeException("Item", _
Item, "Unknown Item requested.")
End Select
Dim i As Integer
Dim alProperties As ArrayList = ibProperties.Properties()
For i = 0 To alProperties.Count - 1
'Build property panel
Console.WriteLine(alProperties(i).ToString())
Next
End Sub

The DirectCast is not needed if Option Strict is not activated (i.e.
ibProperties = New ItemA()).

Finally, through inheritance we can extend an item class to hold more
properties for an item.

Public Class ItemAEx
Inherits ItemA
Public Sub New()
MyBase.New()
Dim extraNames As String() = {"prop_4", "prop_5"}
_propertyNames.Capacity += 2
_propertyNames.AddRange(extraNames)
End Sub
End Class

Now change ItemA to ItemAEx in the BuildPropertiesPanel procedure to see the
new entries printed to the console.

Hope this helps.

Robby.
 
David A. Osborn said:
Basically I have a series of classes that represent items in my program.
These items all have different properties that need to be displayed in a
property window. When the property window geta focus it will check to se
what item is selected and dynamically build the label boxes on itself based
on what the item is.

I will defer you to Robby's reply. That does appear to be the right approach
for the problem you've stated....

Good luck!
LFS
 
This is perfect, Thanks. I actually already have the must override base
class implemented because I wanted any new items forced to implement certain
required functions, so I won't have to make too many changes, just get rid
of the enumerations. Thanks for the help!


Robby said:
Hummm ... not a workable design.
My plan was that it the properties for ItemA or ItemB ever changed
someone would just write a new class that inherits the old one and change
the enumeration,

When the new class inherits from the old class (i.e. Item_A_Class or
Item_B_Class class) it will inherit the enumeration Properties also.
However, the new class will not be able to override the enumeration. It
will only be able to shadow the enumeration. This means that you will
have to completely duplicate the enumeration in each derived class. This
completely defeats a crucial purpose of object orientated design; code
re-use.

An enumeration is not an effective type for storing a list of items. The
call to get the element names in the enumeration is very slow. Using the
element names as the data storage is not what an enumeration is designed
for. There are many other types that implement the IList interface that
are more efficient at storing and retrieving items in a list. Use one of
these instead.

The manner in which you want to use one variable type (Dynamic_Class) to
access methods in two different types (Item_A_Class and Item_B_Class) is
known as polymorphism in object oriented design. In order for you to
implement this with your Item_A_Class and Item_B_Class classes you need
something common to both of them that the Dynamic_Class class can use to
access them. Currently there is nothing common in both classes. You may
think that and enumeration named Properties is common to both but consider
this; the system sees the enumerations as Item_A_Class.Properties and
Item_B_Class.Properties, two completely different enumerations.

So, how do we apply polymorphism to these classes? There is a method that
is slow and prone to run-time error. Simply make Dynamic_Class of type
Object. The Object type is common to all types. Then use late-binding to
access the Properties enumeration. For example,

Dim Dynamic_Class As Object = New Item_A_Class()
Dim properties as String() = _
System.Enum.GetNames(GetType( _
Dynamic_Class.Properties))

As I said above this is a very messy approach as there is no design-time
or compile-time type checking. Therefore, it is very easy for you or
another programmer to make errors that can not be caught until the project
is complied and the particular section of code is run. Also, error
checking late bound errors is generally a hellish experience as the
compiler is only able offer limited support.

As you add more item classes with even more enumerations this code will
become slower and even more prone to late-bound errors.

Do not dispair, there is hope. "We can rebuild [it]. We have the
technology." (Six Million Dollar Man, 1970s)

Anyway ... in order to cleanly get what you ultimately are seeking we need
to redevelope your design to take advantage of inheritance so polymorphism
and hence early-binding and strong type-checking with design-time support
can be applied. First we need to decide on a type to hold your property
data. As stated above any one of the types that implement the IList
interface will suffice. Since we do not want consumers of these objects
to modify, delete or add property names we will use an ArrayList. Now we
can define a class ItemBase that has a protected ArrayList and a public
read only Properties property.

Public MustInherit Class ItemBase
Protected _propertyNames As ArrayList
Public ReadOnly Property Properties() As ArrayList
Get
Return ArrayList.ReadOnly(_propertyNames)
End Get
End Property
End Class

We will make the ItemBase type common to all item classes through
inheritance.

Public Class ItemA
Inherits ItemBase
Public Sub New()
Dim names As String() = {"prop_1", "prop_2", "prop_3"}
_propertyNames = New ArrayList(3)
_propertyNames.AddRange(names)
End Sub
End Class

Public Class ItemB
Inherits ItemBase
Public Sub New()
Dim names As String() = {"prop_A", "prop_B", "prop_C"}
_propertyNames = New ArrayList(3)
_propertyNames.AddRange(names)
End Sub
End Class

Now we can use an ItemBase variable to access the common Properties
property of any item class.

Private Sub BuildPropertiesPanel(ByVal Item As String)
Dim ibProperties As ItemBase
Select Case Item
Case "ItemA"
ibProperties = DirectCast(New ItemA(), _
ItemBase)
Case "ItemB"
ibProperties = DirectCast(New ItemB(), _
ItemBase)
Case Else
Throw New ArgumentOutOfRangeException("Item", _
Item, "Unknown Item requested.")
End Select
Dim i As Integer
Dim alProperties As ArrayList = ibProperties.Properties()
For i = 0 To alProperties.Count - 1
'Build property panel
Console.WriteLine(alProperties(i).ToString())
Next
End Sub

The DirectCast is not needed if Option Strict is not activated (i.e.
ibProperties = New ItemA()).

Finally, through inheritance we can extend an item class to hold more
properties for an item.

Public Class ItemAEx
Inherits ItemA
Public Sub New()
MyBase.New()
Dim extraNames As String() = {"prop_4", "prop_5"}
_propertyNames.Capacity += 2
_propertyNames.AddRange(extraNames)
End Sub
End Class

Now change ItemA to ItemAEx in the BuildPropertiesPanel procedure to see
the new entries printed to the console.

Hope this helps.

Robby.


David A. Osborn said:
Basically I have a series of classes that represent items in my program.
These items all have different properties that need to be displayed in a
property window. When the property window geta focus it will check to se
what item is selected and dynamically build the label boxes on itself
based on what the item is. How I've organized this is each item is its
own class. In each class is an enumeration for that item which contains
the properties for that particular item. So the properties panel needs
to decide what class to use based on the string that is passed to it, and
then loop through the enumerations to dynamically build labels on itself?

I'm looking to do something like this. Obiviously this code/psuedo code,
but hopefully it will portray the idea:


Public Class Item_A_Class
Public Enum Properties
prop_1
prop_2
prop_3
End Enum

Some Funtions

End Class

Public Class Item_B_Class
Public Enum Properties
prop_A
prop_B
prop_C
prop_D
End Enum

Some Functions

End Class


Private Sub Build_Properties_Panel (ByVal Item As String)
If Item = "ItemA" then
Dim Dynamic_Class As Item_A_Class
If Item = "ItemB" then
Dim Dynamic_Class As Item_B_Class
EndIf
'Loop through enumeration for class
Dim properties as String() =
System.enum.GetNames(GetType(Dynamic_Class.properties))
For i As Integer = 0 to name.Length -1
do code to build label

Next

End Sub



My plan was that it the properties for ItemA or ItemB ever changed
someone would just write a new class that inherits the old one and change
the enumeration, and the display could would continue to work perfectly
fine. I suppose I could just do the above loop in each if statement
specifically for the class, but I thought the code would be more concise
if I dynamically pointed Dynamic_Class to which ever class it needed to
be and then only had one loop in the subroutine.

Thanks for the help!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top