VB.NET Overloading problem/question

G

Guest

I am having a problem with overloading. An example:

Public Class Base
...
End Class

Public Class Derived Inherits Base
...
End Class

Public Class Client
Public Sub MethodX()
Dim obj as Base = new Derived()
MethodY(obj)
End Sub

Public Sub MethodY(arg as Base)
...
End Sub

Public Sub MethodY(arg as Derived)
...
End Sub
End Class

MethodX calls the MethodY that has a Base as a parameter, even though obj is
really a Derived object. The MethodY that has a Derived as a parameter would
seem to be a closer match to me. In my actual situation, I am getting the
Derived object elsewhere and do not know what type it is other than it is a
subclass of Base, so I cannot cast it more specifically. I am essentially
trying to do a select...case on the real object type polymorphically. Any
suggestions?

Thanks,
Brian Haynes
 
C

Chad Z. Hower aka Kudzu

=?Utf-8?B?QnJpYW4gSGF5bmVz?= said:
Public Sub MethodY(arg as Base)
...
End Sub

Public Sub MethodY(arg as Derived)
...
End Sub
End Class

MethodX calls the MethodY that has a Base as a parameter, even though
obj is really a Derived object. The MethodY that has a Derived as a

This is normal. Overloads are resolved at build time based on the type of the reference, not the
type of the instance. To resolve at run time would be very slow.


--
Chad Z. Hower (a.k.a. Kudzu) - http://www.hower.org/Kudzu/
"Programming is an art form that fights back"

Make your ASP.NET applications run faster
http://www.atozed.com/IntraWeb/
 
J

Jay B. Harlow [MVP - Outlook]

Brian,
In addition to the other comments.

Consider moving MethodY directly or indirectly into Base as overridable
(directly).

Something like:

| Public Class Base
| ...

Public Overridable Sub MethodY()
' do work for Base's Method Y here.
End Sub

| End Class
|
| Public Class Derived Inherits Base
| ...

Public Overrides Sub MethodY()
' do work for Derived's Method Y here.
End Sub

| End Class
|
| Public Class Client
| Public Sub MethodX()
| Dim obj as Base = new Derived()
obj.MethodY()
| End Sub
|
| End Class

You may need to pass Client as a parameter above if MethodY needs behavior
from Client...


If MethodY "needs" to be in Client, then consider a double dispatch
(indirectly).

| Public Class Base
| ...

Public Overridable Sub MethodY(theClient As Client)
theClient.MethodY(Me)
End Sub

| End Class
|
| Public Class Derived Inherits Base
| ...

Public Overrides Sub MethodY(theClient As Client)
theClient.MethodY(Me)
End Sub

| End Class
|
| Public Class Client
| Public Sub MethodX()
| Dim obj as Base = new Derived()
obj.MethodY(Me)
| End Sub
|
| Public Sub MethodY(arg as Base)

' do work for Base's Method Y here.
| End Sub
|
| Public Sub MethodY(arg as Derived)

' do work for Derived's Method Y here.
| End Sub
| End Class

Using either method may introduce coupling between the classes that is not
desirable, in which case I would consider introducing an Interface that Base
or Client implements to help decouple the classes...

Hope this helps
Jay

|I am having a problem with overloading. An example:
|
| Public Class Base
| ...
| End Class
|
| Public Class Derived Inherits Base
| ...
| End Class
|
| Public Class Client
| Public Sub MethodX()
| Dim obj as Base = new Derived()
| MethodY(obj)
| End Sub
|
| Public Sub MethodY(arg as Base)
| ...
| End Sub
|
| Public Sub MethodY(arg as Derived)
| ...
| End Sub
| End Class
|
| MethodX calls the MethodY that has a Base as a parameter, even though obj
is
| really a Derived object. The MethodY that has a Derived as a parameter
would
| seem to be a closer match to me. In my actual situation, I am getting the
| Derived object elsewhere and do not know what type it is other than it is
a
| subclass of Base, so I cannot cast it more specifically. I am essentially
| trying to do a select...case on the real object type polymorphically. Any
| suggestions?
|
| Thanks,
| Brian Haynes
 
G

Guest

Chad Z. Hower aka Kudzu said:
This is normal. Overloads are resolved at build time based on the type of the reference, not the
type of the instance. To resolve at run time would be very slow.

Example:

Dim i as Object = new Integer
Debug.WriteLine(i.ToString())

The output is 0, not "System.Object". Obviously the ToString call is being
resolved based on the type of the object, not the reference. Isn't it a
little inconsistent for overloads to be resolved on reference type and
overrides to be resolved on object type?
 
G

Guest

Jay B. Harlow said:
Brian,
In addition to the other comments.

Consider moving MethodY directly or indirectly into Base as overridable
(directly).
If MethodY "needs" to be in Client, then consider a double dispatch
(indirectly).


Unfortunately, doing either would be much worse than what I am trying to
avoid. My actual situation is a little more complicated than my example. It
looks like the simplest solution to my problem is going to be doing something
like this:

If typeof obj is Derived Then
MethodY(CType(obj, Derived))
ElseIf typeof obj is Derived2 Then
MethodY(CType(obj, Derived2))
....
Else
MethodY(CType(obj, Base))
End If

Thanks for the suggestions though.
-Brian
 
C

Chad Z. Hower aka Kudzu

=?Utf-8?B?QnJpYW4gSGF5bmVz?= said:
Dim i as Object = new Integer
Debug.WriteLine(i.ToString())

The output is 0, not "System.Object". Obviously the ToString call is
being resolved based on the type of the object, not the reference.
Isn't it a little inconsistent for overloads to be resolved on
reference type and overrides to be resolved on object type?

Because ToString is overridden, which is different than overloading. You are comparing two totally
different concepts.

Overloading compares parameters.

Overriding is on actaul methods of the class.


--
Chad Z. Hower (a.k.a. Kudzu) - http://www.hower.org/Kudzu/
"Programming is an art form that fights back"

Develop ASP.NET applications easier and in less time:
http://www.atozed.com/IntraWeb/
 
G

Guest

Chad Z. Hower aka Kudzu said:
Because ToString is overridden, which is different than overloading. You are comparing two totally
different concepts.

Overloading compares parameters.

Overriding is on actaul methods of the class.

Yes, I realize that. But isn't the override resolution done at run time in
that case? If we have time to resolve the overrides at run time, why can't
we spare time for the overloads? It only really becomes an issue when the
overloads contain types that are related in an ancestor-descendant
relationship by inheritance/implementation. The cases where the overloads
are not related this way could be safely done at runtime.
-Brian
 
C

Chad Z. Hower aka Kudzu

=?Utf-8?B?QnJpYW4gSGF5bmVz?= said:
Yes, I realize that. But isn't the override resolution done at run
time in that case? If we have time to resolve the overrides at run

No, overloads are NEVER done at run time. Overrides are.

Overloads - always at build time.
Overrides - always at compile time.
time, why can't we spare time for the overloads? It only really

Because it would not only be slower, it would require a lot more memory to track it, a VMT of sorts
and it also isnt wanted. The overloads are compile time and thats what its designed for.
becomes an issue when the overloads contain types that are related in
an ancestor-descendant relationship by inheritance/implementation.
The cases where the overloads are not related this way could be safely
done at runtime.

It wouldnt be proper though. Its not a short coming or for performance reasons, its by design.


--
Chad Z. Hower (a.k.a. Kudzu) - http://www.hower.org/Kudzu/
"Programming is an art form that fights back"

Make your ASP.NET applications run faster
http://www.atozed.com/IntraWeb/
 
L

Larry Lard

Brian said:
Unfortunately, doing either would be much worse than what I am trying to
avoid. My actual situation is a little more complicated than my example. It
looks like the simplest solution to my problem is going to be doing something
like this:

If typeof obj is Derived Then
MethodY(CType(obj, Derived))
ElseIf typeof obj is Derived2 Then
MethodY(CType(obj, Derived2))
...
Else
MethodY(CType(obj, Base))
End If

Thanks for the suggestions though.
-Brian

If that is what you want then that is what overriding is for! Define
MethodY in Base, define Overrides MethodY in each Derivedn, then just

MethodY(obj)

will call the appropriate one...
 
P

Phill. W

.. . .
I am getting the Derived object elsewhere and do not know what type
it is other than it is a subclass of Base, so I cannot cast it more
specifically.

Yes, you can, so long as you first ask it what type it actually is!
This might get you a bit closer to where you want to be ...

Dim obj as Base = GetPossiblyDerivedObject()

If TypeOf obj Is Derived Then
MethodY( DirectCast( obj, Derived ) )
Else
MethodY( obj )
End If

HTH,
Phill W.
 
G

Guest

Larry Lard said:
If that is what you want then that is what overriding is for! Define
MethodY in Base, define Overrides MethodY in each Derivedn, then just

MethodY(obj)

will call the appropriate one...

Thanks for your comments. I see how this would work in general, but my
situation is something like this: (typing this off the top of my head so
syntax might be slightly off...)

Public MustInherit Class Message
...
Public Overrides MustInherit Function ToString() as String
...
End Class

Public Class BodyMessage Inherits Message
Private body as String
...
Public Property Body as String
...
End Property
Public Overrides Function ToString() as String
Return Body
End Function
End Class

Public Class SubjectBodyMessage Inherits Message
Private body as String
Private subject as String

Public Property Body as String
...
End Property
Public Property Subject as String
...
End Property
Public Overrides Function ToString() as String
Return Subject & Environment.NewLine & Body
End Function
End Class

---< form code >---
Dim message as Message = GetMessage()
txtSubject.Text = GetSubjectText(message)
txtBody.Text = GetBodyText(message)

Private Function GetSubjectText(message as Message) as String
Return message.ToString()
End Function

Private Function GetSubjectText(message as SubjectBodyMessage) as String
Return message.Subject
End Function

Private Function GetBodyText(message as Message) as String
Return message.ToString()
End Function

Private Function GetBodyText(message as SubjectBodyMessage) as String
Return message.Body
End Function

So what I am really looking for is for my form to handle different types of
messages as gracefully as it can. If I have defined an overload that matches
the type of the object exactly, use that, otherwise, move up the hierarchy
until it finds a match. The worst case would be if the message was of a type
the form didn't know and it would have to resort to using the ToString. It
wouldn't make much sense to add a subject method to the BodyMessage class
since it doesn't represent a message with a subject. In the future I might
have other message sections in other derived classes.

If I am going about this in a foolish way, please make suggestions. Thank
you to all who have taken the time to respond so far.
-Brian
 
J

Jay B. Harlow [MVP - Outlook]

Brian,
It seems you are trying to make ToString do too much.

| It
| wouldn't make much sense to add a subject method to the BodyMessage class
| since it doesn't represent a message with a subject.
I would put both Subject & Body as Overridable in Message, as Messages may
have a Subject or they may have a Body, also its the "key" to ensuring
Message is as generic as possible. I would consider adding HasSubject &
HasBody properties, ala the System.IO.Stream class. Not all specific Stream
classes are seekable (NetworkStream for example). Although Stream has a Seek
method, NetworkStream.Seek throws an NotSupportedException if you attempt to
call it, the NetworkStream.CanSeek returns false...

| Public MustInherit Class Message
| ...

Public Overridable Readonly Property HasBody As Boolean
Get
Return False
End Get
End Property

Public Overridable Property Body As String
Get
Return ToString()
End Get
Set
Throw New NotSupportedException
End Get
End Property

Public Overridable Property Subject As String
Get
Return ToString()
End Get
Set
Throw New NotSupportedException
End Get
End Property

| Public Overrides MustInherit Function ToString() as String
| ...
| End Class
|

BodyMessage & SubjectBodyMessage would (should?) then simply need to add
Overrides on the Body or Subject properties respectively.

| Public Class BodyMessage Inherits Message
| Private body as String
| ...
Public Overrides Readonly Property HasBody As Boolean
Get
Return True
End Get
End Property

| Public Property Body as String
| ...
| End Property
| Public Overrides Function ToString() as String
| Return Body
| End Function
| End Class


Your form code would then be reduced to:

| ---< form code >---
| Dim message as Message = GetMessage()
| txtSubject.Text = message.Subject
| txtBody.Text = message.Body

The need to overload GetSubjectText is removed.


Your form code should not (*should not*) know about specific types of
messages (BodyMessage & SubjectBodyMessage), it should (*should*) only know
of the base Message type. Using polymorphism via Overriding will allow your
form to access the specifics of specific types of messages. By not coupling
your form to BodyMessage & SubjectBodyMessage you allow new types of
messages to be introduced without needing a lot of changes to your form
code.

My concern is introducing unbounded recursion. Message.Body calls ToString,
which may call Message.Body, which calls ToString... Right now I'm not
seeing an easy way to avoid that, I would need more details on what you are
doing to know how or if you can avoid it... The HasBody & HasSubject
properties may help here...


| If I have defined an overload that matches
| the type of the object exactly, use that, otherwise, move up the hierarchy
| until it finds a match.
Overrides are a runtime feature, the "best match" for the method is selected
based on the runtime type of the object. The "best match" is based on the
specific type of object & if the specific type overrides the method or not.

Overloads are a compile time feature, the best match for the method is
selected based on the compile time type of variable.

Hope this helps
Jay

| "Larry Lard" wrote:
| > If that is what you want then that is what overriding is for! Define
| > MethodY in Base, define Overrides MethodY in each Derivedn, then just
| >
| > MethodY(obj)
| >
| > will call the appropriate one...
|
| Thanks for your comments. I see how this would work in general, but my
| situation is something like this: (typing this off the top of my head so
| syntax might be slightly off...)
|
| Public MustInherit Class Message
| ...
| Public Overrides MustInherit Function ToString() as String
| ...
| End Class
|
| Public Class BodyMessage Inherits Message
| Private body as String
| ...
| Public Property Body as String
| ...
| End Property
| Public Overrides Function ToString() as String
| Return Body
| End Function
| End Class
|
| Public Class SubjectBodyMessage Inherits Message
| Private body as String
| Private subject as String
|
| Public Property Body as String
| ...
| End Property
| Public Property Subject as String
| ...
| End Property
| Public Overrides Function ToString() as String
| Return Subject & Environment.NewLine & Body
| End Function
| End Class
|
| ---< form code >---
| Dim message as Message = GetMessage()
| txtSubject.Text = GetSubjectText(message)
| txtBody.Text = GetBodyText(message)
|
| Private Function GetSubjectText(message as Message) as String
| Return message.ToString()
| End Function
|
| Private Function GetSubjectText(message as SubjectBodyMessage) as String
| Return message.Subject
| End Function
|
| Private Function GetBodyText(message as Message) as String
| Return message.ToString()
| End Function
|
| Private Function GetBodyText(message as SubjectBodyMessage) as String
| Return message.Body
| End Function
|
| So what I am really looking for is for my form to handle different types
of
| messages as gracefully as it can. If I have defined an overload that
matches
| the type of the object exactly, use that, otherwise, move up the hierarchy
| until it finds a match. The worst case would be if the message was of a
type
| the form didn't know and it would have to resort to using the ToString.
It
| wouldn't make much sense to add a subject method to the BodyMessage class
| since it doesn't represent a message with a subject. In the future I
might
| have other message sections in other derived classes.
|
| If I am going about this in a foolish way, please make suggestions. Thank
| you to all who have taken the time to respond so far.
| -Brian
 
L

Larry Lard

Brian said:
Thanks for your comments. I see how this would work in general, but my
situation is something like this: (typing this off the top of my head so
syntax might be slightly off...)

Public MustInherit Class Message
...
Public Overrides MustInherit Function ToString() as String
...
End Class

Public Class BodyMessage Inherits Message
Private body as String
...
Public Property Body as String
...
End Property
Public Overrides Function ToString() as String
Return Body
End Function
End Class

Public Class SubjectBodyMessage Inherits Message
Private body as String
Private subject as String

Public Property Body as String
...
End Property
Public Property Subject as String
...
End Property
Public Overrides Function ToString() as String
Return Subject & Environment.NewLine & Body
End Function
End Class

---< form code >---
Dim message as Message = GetMessage()
txtSubject.Text = GetSubjectText(message)
txtBody.Text = GetBodyText(message)

Private Function GetSubjectText(message as Message) as String
Return message.ToString()
End Function

Private Function GetSubjectText(message as SubjectBodyMessage) as String
Return message.Subject
End Function

Private Function GetBodyText(message as Message) as String
Return message.ToString()
End Function

Private Function GetBodyText(message as SubjectBodyMessage) as String
Return message.Body
End Function

(First a stylistic point: when you write a method called GetX it
suggests to me a property called X - in fact a ReadOnly property since
there is no SetX)

So here, a SubjectText is something that all Messages are required to
produce - for most messages ths ToString is returned, but
SubjectBodyMessages have a more specific behavior:

(in Message)
Public Overridable ReadOnly Property SubjectText() As String
Get
Return Me.ToString
End Get
End Property

(in BodyMessage)
' no redefinition of SubjectText, so the base class definition will be
used
' (from Message)

(in SubjectBodyMessage)
Public Overrides ReadOnly Property SubjectText() As String
Get
Return Me.subject
End Get
End Property

Similarly, all Messages are required to come up with a BodyText, but
plain Messages just offer their ToString, while BodyMessages offer
something more specific: (also, I am here deriving SubjectBodyMessage
from BodyMessage)

(in Message)
Public Overridable ReadOnly Property BodyText() As String
Get
Return Me.ToString
End Get
End Property

(in BodyMessage)
Public Overrides ReadOnly Property BodyText() As String
Get
Return Me.body
End Get
End Property

(in SubjectBodyMessage)
' no redefinition of BodyText, so the base class definition will be
used
' (from BodyMessage)



The pay-off for getting the classes right is that client code (your
form code in this case) is startlingly simple, and importantly *doesn't
know about the internal details* of the classes it calls.

Dim message as Message = GetMessage()

As a *consumer* of the various Message classes we do not care what
particular kind of Message we have, because we can just say:

txtSubject.Text = message.SubjectText
txtBody.Text = message.BodyText

and the actual gory details of what we get returned are dealt with
where they should be - within the various Message classes.

The principle at work here is that you identify all the *behavior* that
the various classes have *in common*, then declare that behavior at the
most general level, while *defining* it at the appropriate level:

desired behavior: we want to be able to get *some* String subject and
body from *all* messages
therefore: subject and body are properties of a message

desired behavior: BodyMessages should return their true body text,
otherwise body text is some fallback value
therefore: define the fallback value at the general Message level, then
override that at the BodyMessage level

desired behavior: SubjectBodyMessages should return their true subject
text, otherwise subject text is some fallback value
therefore: define the fallback value at the general Message level, then
override that at the SubjectBodyMessage level
 
J

Jay B. Harlow [MVP - Outlook]

Larry,
Doh! that's simpler then the way I did it.

Simpler is usually better.

Jay

|
|
| Brian Haynes wrote:
| > "Larry Lard" wrote:
| > > If that is what you want then that is what overriding is for! Define
| > > MethodY in Base, define Overrides MethodY in each Derivedn, then just
| > >
| > > MethodY(obj)
| > >
| > > will call the appropriate one...
| >
| > Thanks for your comments. I see how this would work in general, but my
| > situation is something like this: (typing this off the top of my head so
| > syntax might be slightly off...)
| >
| > Public MustInherit Class Message
| > ...
| > Public Overrides MustInherit Function ToString() as String
| > ...
| > End Class
| >
| > Public Class BodyMessage Inherits Message
| > Private body as String
| > ...
| > Public Property Body as String
| > ...
| > End Property
| > Public Overrides Function ToString() as String
| > Return Body
| > End Function
| > End Class
| >
| > Public Class SubjectBodyMessage Inherits Message
| > Private body as String
| > Private subject as String
| >
| > Public Property Body as String
| > ...
| > End Property
| > Public Property Subject as String
| > ...
| > End Property
| > Public Overrides Function ToString() as String
| > Return Subject & Environment.NewLine & Body
| > End Function
| > End Class
| >
| > ---< form code >---
| > Dim message as Message = GetMessage()
| > txtSubject.Text = GetSubjectText(message)
| > txtBody.Text = GetBodyText(message)
| >
| > Private Function GetSubjectText(message as Message) as String
| > Return message.ToString()
| > End Function
| >
| > Private Function GetSubjectText(message as SubjectBodyMessage) as String
| > Return message.Subject
| > End Function
| >
| > Private Function GetBodyText(message as Message) as String
| > Return message.ToString()
| > End Function
| >
| > Private Function GetBodyText(message as SubjectBodyMessage) as String
| > Return message.Body
| > End Function
|
| (First a stylistic point: when you write a method called GetX it
| suggests to me a property called X - in fact a ReadOnly property since
| there is no SetX)
|
| So here, a SubjectText is something that all Messages are required to
| produce - for most messages ths ToString is returned, but
| SubjectBodyMessages have a more specific behavior:
|
| (in Message)
| Public Overridable ReadOnly Property SubjectText() As String
| Get
| Return Me.ToString
| End Get
| End Property
|
| (in BodyMessage)
| ' no redefinition of SubjectText, so the base class definition will be
| used
| ' (from Message)
|
| (in SubjectBodyMessage)
| Public Overrides ReadOnly Property SubjectText() As String
| Get
| Return Me.subject
| End Get
| End Property
|
| Similarly, all Messages are required to come up with a BodyText, but
| plain Messages just offer their ToString, while BodyMessages offer
| something more specific: (also, I am here deriving SubjectBodyMessage
| from BodyMessage)
|
| (in Message)
| Public Overridable ReadOnly Property BodyText() As String
| Get
| Return Me.ToString
| End Get
| End Property
|
| (in BodyMessage)
| Public Overrides ReadOnly Property BodyText() As String
| Get
| Return Me.body
| End Get
| End Property
|
| (in SubjectBodyMessage)
| ' no redefinition of BodyText, so the base class definition will be
| used
| ' (from BodyMessage)
|
|
|
| The pay-off for getting the classes right is that client code (your
| form code in this case) is startlingly simple, and importantly *doesn't
| know about the internal details* of the classes it calls.
|
| Dim message as Message = GetMessage()
|
| As a *consumer* of the various Message classes we do not care what
| particular kind of Message we have, because we can just say:
|
| txtSubject.Text = message.SubjectText
| txtBody.Text = message.BodyText
|
| and the actual gory details of what we get returned are dealt with
| where they should be - within the various Message classes.
|
| The principle at work here is that you identify all the *behavior* that
| the various classes have *in common*, then declare that behavior at the
| most general level, while *defining* it at the appropriate level:
|
| desired behavior: we want to be able to get *some* String subject and
| body from *all* messages
| therefore: subject and body are properties of a message
|
| desired behavior: BodyMessages should return their true body text,
| otherwise body text is some fallback value
| therefore: define the fallback value at the general Message level, then
| override that at the BodyMessage level
|
| desired behavior: SubjectBodyMessages should return their true subject
| text, otherwise subject text is some fallback value
| therefore: define the fallback value at the general Message level, then
| override that at the SubjectBodyMessage level
|
| --
| Larry Lard
| Replies to group please
|
 
G

Guest

Jay B. Harlow said:
| wouldn't make much sense to add a subject method to the BodyMessage class
| since it doesn't represent a message with a subject.
I would put both Subject & Body as Overridable in Message, as Messages may
have a Subject or they may have a Body, also its the "key" to ensuring
Message is as generic as possible. I would consider adding HasSubject &
HasBody properties, ala the System.IO.Stream class. Not all specific Stream
classes are seekable (NetworkStream for example). Although Stream has a Seek
method, NetworkStream.Seek throws an NotSupportedException if you attempt to
call it, the NetworkStream.CanSeek returns false...

Thanks for contributing thought and time to this. I appreciate it. :)

My first concern if I start adding properties to the base Message that might
not be supported by the clients is that every time I want to create a new
message type, I have to add the additional properties to Message and write
HasX methods for all of my other Message subclasses.

For example, say I have two forms in different applications that can receive
and display these messages. One form supports messages with subject and body
and the other supports messages that have subject and body and optionally an
object that is used to trigger some action by the program. If form #1 gets a
message with subject, body, and an object, it should behave nicely and
display the subject and body and ignore the object (it doesn't know what to
do with it anyway). Form #2 should display the subject and body and work
with the object. But it seems incorrect to add the object property/method to
the Message class because it is not a part of all messages, only a certain
type.

Obviously, if each application only received messages that they could 100%
support this would be much easier. I am trying to allow applications to
handle messages they are not able to support 100% however because I believe
if Application A sends a message to Application B it is better for the user
of B to get *something* rather than *nothing*.
My concern is introducing unbounded recursion. Message.Body calls ToString,
which may call Message.Body, which calls ToString... Right now I'm not
seeing an easy way to avoid that, I would need more details on what you are
doing to know how or if you can avoid it... The HasBody & HasSubject
properties may help here...

That would be icky. The only defense I can offer to that is that I
generally don't code that way. Properties may refer to variables, nothing in
the class depends on ToString.

Thanks for your suggestions,
Brian
 
J

Jay B. Harlow [MVP - Outlook]

Brian,
| My first concern if I start adding properties to the base Message that
might
| not be supported by the clients is that every time I want to create a new
| message type, I have to add the additional properties to Message and write
| HasX methods for all of my other Message subclasses.
Yes that's a valid concern, however I find its better to only couple to
Message, rather then couple to each specific class.

Another option I thought about, but have not worked out the specifics is to
introduce interfaces for each "part" you may be going after.

Incomplete example:

Public Interface IBody
Property Body As String
End Interface

Public Interface ISubject
Property Subject As String
End Interface

Then BodyMessage & SubjectBodyMessage would implement the interfaces:

Public Class BodyMessage
Inherits Message
Implements IBody

End Class

Public Class SubjectBodyMessage
Inherits Message
Implements IBody
Implements ISubject

End Class

Then would check for the above interface & act appropriately

Private Function GetSubjectText(message as Message) as String
If TypeOf message Is ISubject Then
Return DirectCast(message, ISubject).Subject
Else
Return message.ToString()
End If
End Function

The Interface itself then acts as the HasMethod.

Your form code is only coupled to the interfaces & not to the specific types
of messages.

I would expect this method has its own pluses & minuses also.

Hope this helps
Jay


| "Jay B. Harlow [MVP - Outlook]" wrote:
| > | wouldn't make much sense to add a subject method to the BodyMessage
class
| > | since it doesn't represent a message with a subject.
| > I would put both Subject & Body as Overridable in Message, as Messages
may
| > have a Subject or they may have a Body, also its the "key" to ensuring
| > Message is as generic as possible. I would consider adding HasSubject &
| > HasBody properties, ala the System.IO.Stream class. Not all specific
Stream
| > classes are seekable (NetworkStream for example). Although Stream has a
Seek
| > method, NetworkStream.Seek throws an NotSupportedException if you
attempt to
| > call it, the NetworkStream.CanSeek returns false...
|
| Thanks for contributing thought and time to this. I appreciate it. :)
|
| My first concern if I start adding properties to the base Message that
might
| not be supported by the clients is that every time I want to create a new
| message type, I have to add the additional properties to Message and write
| HasX methods for all of my other Message subclasses.
|
| For example, say I have two forms in different applications that can
receive
| and display these messages. One form supports messages with subject and
body
| and the other supports messages that have subject and body and optionally
an
| object that is used to trigger some action by the program. If form #1
gets a
| message with subject, body, and an object, it should behave nicely and
| display the subject and body and ignore the object (it doesn't know what
to
| do with it anyway). Form #2 should display the subject and body and work
| with the object. But it seems incorrect to add the object property/method
to
| the Message class because it is not a part of all messages, only a certain
| type.
|
| Obviously, if each application only received messages that they could 100%
| support this would be much easier. I am trying to allow applications to
| handle messages they are not able to support 100% however because I
believe
| if Application A sends a message to Application B it is better for the
user
| of B to get *something* rather than *nothing*.
|
| > My concern is introducing unbounded recursion. Message.Body calls
ToString,
| > which may call Message.Body, which calls ToString... Right now I'm not
| > seeing an easy way to avoid that, I would need more details on what you
are
| > doing to know how or if you can avoid it... The HasBody & HasSubject
| > properties may help here...
|
| That would be icky. The only defense I can offer to that is that I
| generally don't code that way. Properties may refer to variables, nothing
in
| the class depends on ToString.
|
| Thanks for your suggestions,
| Brian
 

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

Top