Polymorphism question

  • Thread starter Thread starter Kees de Winter
  • Start date Start date
K

Kees de Winter

HI,

How can I access the fields and methods of a subclass in a variable that was
declared as a parent-class and instantiated as a subclass.

Public Class Communication
Public Response As Message
some more stuff
End Class


Public Class Message
some fields, methods etc.
End Class

Public Class Letter
Inherits Message
Public Stamp As String
End Class

Public Class Email
Inherits Message
Public Emailaddress As String
End Class


Now in the main procedure, say pageload, I'd like to easily use code like
this:

Dim Communication1 As New Communication
Communication1.Response.EmailAddress = "bla"

But of course it's not possible, I need to use:
CType(Communication1.Response, Email).EmailAddress = "bla"

Is there a way to accomplish this? I have also tried by providing a
Enum-type variable in the constructor of the Communication class and then to
instantiate "Response" with the chosen subclass but to no avail.

Thank you for your time.
 
First of all, the Response property of the Communication class is not an
instance of the Email class, any more than a vehicle is a truck. Let me put
it this way: You're talking about inheritance here. A car is a vehicle; it
inherits vehicle. A truck is a vehicle; it inherits vehicle. But a car is
not a truck. Let's substitute the words "vehicle," "car" and "truck" for
your problem. The Communication class has a public field that is a
"vehicle." You want to be able to treat it as a truck before you define what
type of vehicle it is. Since you don't know what it is, you can only treat
it like a vehicle, that is, access the properties of it which belong to the
vehicle class, both cars and trucks.

In fact, you haven't even instantiated it, that is, created an instance of
the class to work with. You are assigning values to properties of something
that doesn't exist yet. When you create a field, you only create storage
space for something of a certain type. If it is a parent type, any class
which inherits that type is storable there. However, unless the specific
type of the class is known, your app cannot work with the properties of that
specific class. You have to define an instance of the class you want it to
be, assign it to the field of the class ity resides in, and then treat it
like the specific class you have assigned.

--
HTH,

Kevin Spencer
Microsoft MVP

Printing Components, Email Components,
Networking Components, Controls, much more.
DSI PrintManager, Miradyne Component Libraries:
http://www.miradyne.net
 
Oops in my pseudo-code I forgot the constructor :

Public Class Communication
Public Sub New(ByVal enumType1 as enumType)
if enumType1 = enumType.Email Then Response = New Email
[..]
End Sub
Public Response As Message
End Class

Then the declaration is:
Dim Communication1 As New Communication(enumType.Email)
Communication1.Response.EmailAddress = "bla" << not possible


Thank you Kevin however with this constructor added, I thought the Response
field could know that it should be an Email because it has been instantiated
as such. However apparently it doesn't look at that and sticks with how it
was declared. I don't want to fill my pages with CType's, is there a more
elegant way of coding this?

--
Kees


Kevin Spencer said:
First of all, the Response property of the Communication class is not an
instance of the Email class, any more than a vehicle is a truck. Let me put
it this way: You're talking about inheritance here. A car is a vehicle; it
inherits vehicle. A truck is a vehicle; it inherits vehicle. But a car is
not a truck. Let's substitute the words "vehicle," "car" and "truck" for
your problem. The Communication class has a public field that is a
"vehicle." You want to be able to treat it as a truck before you define what
type of vehicle it is. Since you don't know what it is, you can only treat
it like a vehicle, that is, access the properties of it which belong to the
vehicle class, both cars and trucks.

In fact, you haven't even instantiated it, that is, created an instance of
the class to work with. You are assigning values to properties of something
that doesn't exist yet. When you create a field, you only create storage
space for something of a certain type. If it is a parent type, any class
which inherits that type is storable there. However, unless the specific
type of the class is known, your app cannot work with the properties of that
specific class. You have to define an instance of the class you want it to
be, assign it to the field of the class ity resides in, and then treat it
like the specific class you have assigned.

--
HTH,

Kevin Spencer
Microsoft MVP

Printing Components, Email Components,
Networking Components, Controls, much more.
DSI PrintManager, Miradyne Component Libraries:
http://www.miradyne.net
 
Kees,

As Kevin has pointed out, the problem is that the code accessing your
Communication instance does not (and cannot) know what type the Response
property is other than it derives from Response. Look at it the other way,
if the Response was a Letter, what would happen when it got to the line:

Communication1.Response.EmailAddress = "bla"

The EmailAddress property does not exist on the Letter class!!

If the properties you want to access is common to all instances of Response,
then you could either implement it in the Response class, or declare an
abstract (MustImplement) property in Response and implement it in the sub
classes. If the property is specific to a certain subclass, then you MUST
cast to the appropriate type to be able to access it.

HTH,

Bill



Kees de Winter said:
Oops in my pseudo-code I forgot the constructor :

Public Class Communication
Public Sub New(ByVal enumType1 as enumType)
if enumType1 = enumType.Email Then Response = New Email
[..]
End Sub
Public Response As Message
End Class

Then the declaration is:
Dim Communication1 As New Communication(enumType.Email)
Communication1.Response.EmailAddress = "bla" << not possible


Thank you Kevin however with this constructor added, I thought the Response
field could know that it should be an Email because it has been instantiated
as such. However apparently it doesn't look at that and sticks with how it
was declared. I don't want to fill my pages with CType's, is there a more
elegant way of coding this?
 
Ok, thanks for your help. I got it now, what I wanted to do is just not
possible.

Kees


Bill said:
Kees,

As Kevin has pointed out, the problem is that the code accessing your
Communication instance does not (and cannot) know what type the Response
property is other than it derives from Response. Look at it the other way,
if the Response was a Letter, what would happen when it got to the line:

Communication1.Response.EmailAddress = "bla"

The EmailAddress property does not exist on the Letter class!!

If the properties you want to access is common to all instances of Response,
then you could either implement it in the Response class, or declare an
abstract (MustImplement) property in Response and implement it in the sub
classes. If the property is specific to a certain subclass, then you MUST
cast to the appropriate type to be able to access it.

HTH,

Bill



Kees de Winter said:
Oops in my pseudo-code I forgot the constructor :

Public Class Communication
Public Sub New(ByVal enumType1 as enumType)
if enumType1 = enumType.Email Then Response = New Email
[..]
End Sub
Public Response As Message
End Class

Then the declaration is:
Dim Communication1 As New Communication(enumType.Email)
Communication1.Response.EmailAddress = "bla" << not possible


Thank you Kevin however with this constructor added, I thought the Response
field could know that it should be an Email because it has been instantiated
as such. However apparently it doesn't look at that and sticks with how it
was declared. I don't want to fill my pages with CType's, is there a more
elegant way of coding this?

--
Kees


Kevin Spencer said:
First of all, the Response property of the Communication class is not an
instance of the Email class, any more than a vehicle is a truck. Let
me
put
it this way: You're talking about inheritance here. A car is a vehicle; it
inherits vehicle. A truck is a vehicle; it inherits vehicle. But a car is
not a truck. Let's substitute the words "vehicle," "car" and "truck" for
your problem. The Communication class has a public field that is a
"vehicle." You want to be able to treat it as a truck before you
define
what
type of vehicle it is. Since you don't know what it is, you can only treat
it like a vehicle, that is, access the properties of it which belong
to
the
vehicle class, both cars and trucks.

In fact, you haven't even instantiated it, that is, created an instance of
the class to work with. You are assigning values to properties of something
that doesn't exist yet. When you create a field, you only create storage
space for something of a certain type. If it is a parent type, any class
which inherits that type is storable there. However, unless the specific
type of the class is known, your app cannot work with the properties
of
that
specific class. You have to define an instance of the class you want it to
be, assign it to the field of the class ity resides in, and then treat it
like the specific class you have assigned.

--
HTH,

Kevin Spencer
Microsoft MVP

Printing Components, Email Components,
Networking Components, Controls, much more.
DSI PrintManager, Miradyne Component Libraries:
http://www.miradyne.net

HI,

How can I access the fields and methods of a subclass in a variable that
was
declared as a parent-class and instantiated as a subclass.

Public Class Communication
Public Response As Message
some more stuff
End Class


Public Class Message
some fields, methods etc.
End Class

Public Class Letter
Inherits Message
Public Stamp As String
End Class

Public Class Email
Inherits Message
Public Emailaddress As String
End Class


Now in the main procedure, say pageload, I'd like to easily use code like
this:

Dim Communication1 As New Communication
Communication1.Response.EmailAddress = "bla"

But of course it's not possible, I need to use:
CType(Communication1.Response, Email).EmailAddress = "bla"

Is there a way to accomplish this? I have also tried by providing a
Enum-type variable in the constructor of the Communication class and then
to
instantiate "Response" with the chosen subclass but to no avail.

Thank you for your time.
 
The type must be known. Since the parent class is the one declared, for the
code to recognize a derived class as what it is, it needs to be told.

--
HTH,

Kevin Spencer
Microsoft MVP

Printing Components, Email Components,
Networking Components, Controls, much more.
DSI PrintManager, Miradyne Component Libraries:
http://www.miradyne.net

Kees de Winter said:
Oops in my pseudo-code I forgot the constructor :

Public Class Communication
Public Sub New(ByVal enumType1 as enumType)
if enumType1 = enumType.Email Then Response = New Email
[..]
End Sub
Public Response As Message
End Class

Then the declaration is:
Dim Communication1 As New Communication(enumType.Email)
Communication1.Response.EmailAddress = "bla" << not possible


Thank you Kevin however with this constructor added, I thought the
Response
field could know that it should be an Email because it has been
instantiated
as such. However apparently it doesn't look at that and sticks with how it
was declared. I don't want to fill my pages with CType's, is there a more
elegant way of coding this?
 
Back
Top