inherited queue class

  • Thread starter Thread starter Brian Henry
  • Start date Start date
B

Brian Henry

If i inherite a queue class into my class, and do an override of the enqueue
member, how would i then go about actually doing an enqueue of an item? I am
a little confused on this one... does over ride just add aditional code
ontop of the current class or completely over ride it in vb? I am use to C++
this is the first inherited thing I've done in VB.NET... I'm a little unsure
of diffrences, could someone explain this to me some? thanks!
 
Brian,
Overiding in VB.NET works effectively the same as defining a virtual
function in C++.

You can use MyBase to call a method in the base class

In the simplest case, this is how you override the enqueue & dequeue
methods:

Public Class MyQueue
Inherits Queue

Public Overrides Function Dequeue() As Object
Return MyBase.Dequeue
End Function

Public Overrides Sub Enqueue(ByVal obj As Object)
MyBase.Enqueue(obj)
End Sub

End Class

Hope this helps
Jay
 
thanks that helped clear up stuff a lot

Jay B. Harlow said:
Brian,
Overiding in VB.NET works effectively the same as defining a virtual
function in C++.

You can use MyBase to call a method in the base class

In the simplest case, this is how you override the enqueue & dequeue
methods:

Public Class MyQueue
Inherits Queue

Public Overrides Function Dequeue() As Object
Return MyBase.Dequeue
End Function

Public Overrides Sub Enqueue(ByVal obj As Object)
MyBase.Enqueue(obj)
End Sub

End Class

Hope this helps
Jay
 
Ah ha! So you could make a MyQueue that was specific as to the type of the
object by simply making those declarations in your MyQueue?

Public Class IntQueue
Inherits Queue

Public Overrides Function Dequeue() as Integer
Return MyBase.Dequeue
End Function

Public Overrides Sub Enqueue(ByVal obj As Integer)
MyBase.Enqueue(obj)
End Sub

End Class
 
Ot,
Unfortunately not! Or is it Fortunately no!

An Override requires the parameters & return type to match the base type.

You can use Overloads or Shadows to change parameter types, however if you
are changing just return type you need to use Shadows.

Be warned that Shadows DOES NOT operate polymorphically, if you put IntQueue
into a Queue variable you will call the base methods. Where as Overrides is
polymorphic, so placing IntQueue into a Queue variable you will still call
the overriden method.

Hope this helps
Jay
 
Public Class IntQueue
Inherits Queue
Public Shadows Sub Enqueue(ByVal obj As Integer)
Console.WriteLine("IntQueue.Enqueue entered")
MyBase.Enqueue(obj)
End Sub

Public Shadows Function Dequeue() As Integer
Console.WriteLine("IntQueue.Dequeue entered")
Return Cint(MyBase.Dequeue())
End Function
End Class

Yes, changing to the Shadows keyword works almost the way I want.

Dim integerQ As IntQueue = New IntQueue

Dim anotherQ As Queue = New IntQueue

If I use integerQ.Enqueue the IntelliSense prompts me for an integer.
Passing a string causes a runtime error which is just right. Or if Option
Strict On the IDE complains about the implicit conversion.

However, the anotherQ.Enqueue avoids my shadows routines altogether.
Wouldn't really expect this since it is an IntQueue object, not a Queue
object. I think this what you meant when you said Shadows does not operate
polymorphically. Apparently when it was Cast from type IntQueue to type
Queue when the object anotherQ was created it lost its flavor.

Dim yetanotherQ as IntQueue = New Queue ' fails right here with
invalid cast

Thanks for your help, Jay. I am making progress! Not bad for 2 months
learning VB.NET, eh?
 
Ot,
However, the anotherQ.Enqueue avoids my shadows routines altogether.
Wouldn't really expect this since it is an IntQueue object, not a Queue
object. I think this what you meant when you said Shadows does not operate
polymorphically. Apparently when it was Cast from type IntQueue to type
Queue when the object anotherQ was created it lost its flavor.
Dim anotherQ As Queue = New IntQueue

The IntQueue was not "cast" to a Queue object per se, IntQueue inherits from
Queue so it is a Queue! You can assign a Queue object to a Queue variable.
Casting comes into play when you have a less specific variable (Queue) and
you are trying to place it in a more specific variable (IntQueue). The cast
will succeed as long as the less specific variable does in deed have an
object of the more specific type.
Dim integerQ As IntQueue
Dim anotherQ As Queue = New IntQueue

integerQ = DirectCast(anotherQ, IntQueue)

It avoids your routine because you Shadowed Enqueue & Dequeue, the Shadowed
version are only available when you have a variable of type IntQueue, when
you have a variable of type Queue, the compiler only sees the Queue
versions. Try the following:
Public Class IntQueue
Inherits Queue
Public Overrides Sub Enqueue(ByVal obj As Object)
Console.WriteLine("IntQueue.Enqueue entered")
MyBase.Enqueue(obj)
End Sub

Public Overrides Function Dequeue() As Object
Console.WriteLine("IntQueue.Dequeue entered")
Return Cint(MyBase.Dequeue())
End Function
End Class
Dim anotherQ As Queue = New IntQueue

Your routines will be seen as you are overriding the base functions.
Dim yetanotherQ as IntQueue = New Queue ' fails right here with
invalid cast
Fails because IntQueue is more specific then Queue. In other words a Queue
object is not always an IntQueue object...

Generally I will use encapsulation to create an IntQueue object, instead of
Inheritance, as you cannot change the types of the overriden types. Rarely
do you want to Shadow a method, as the result is rarely what you want. The
only place I (currently) use Shadows normally is when I have creating
derived controls and I need to change one of the Attributes on the
properties. I shadow the base property so I can add the attribute, however
the shadowed property does not attempt to change types, it simply calls the
base function. Overall the rule I use for Shadows is its use is the
exception not the norm!
Public Class IntQueue
private m_queue As New Queue
Public Sub Enqueue(ByVal obj As Integer)
Console.WriteLine("IntQueue.Enqueue entered")
m_queue.Enqueue(obj)
End Sub

Public Function Dequeue() As Integer
Console.WriteLine("IntQueue.Dequeue entered")
Return DirectCast(m_queue.Dequeue(), Integer)
End Function
End Class

Remember CInt & CType are conversion operators, while DirectCast is casting.
(CType will cast in some cases and convert in most cases, hence I use
DirectCast unless I have to use CType).

Hope this helps
Jay
 
Jay B. Harlow said:
Ot,
It avoids your routine because you Shadowed Enqueue & Dequeue, the Shadowed
version are only available when you have a variable of type IntQueue, when
you have a variable of type Queue, the compiler only sees the Queue
versions.

I am getting what I want. That is, objects of type IntQueue are
type-specific queues. (Well, I have to shadow Contains as well if I want
to make that one type-specific, but the idea is there.)

Further discussion is simply for the sake of learning more.

Actually saying Dim aQ as Queue = New IntQueue would be a programming error
in my mind.

Try the following:

I tried this and when I changed the Shadows keyword to Overrides the IDE
tell me
<qoute>
sub 'Enqueue' cannot be declared 'Overrides' because it does not override
a sub in a base class.
</quote>
and also
<quote>
sub 'Enqueue' shadows an overloadable member declared in the base class
'Queue'. If you want to overload the base method, this method must be
declared 'Overloads'.
</quote>

I am not quite sure what the first error message is telling me. It seems
that "Enqueue" is a sub in the base class, but the error message says it
isn't. Confused as always. There seems no way to use Overrides.

The second error message (when I use the Overrides not Shadows) says it
shadows? More confusion. Well, anyway, I tried overloading and it
behaves almost the way I want, too:

Option Strict On
Public Class IntQueue
Inherits Queue
Public Overloads Sub Enqueue(ByVal obj As Integer)
Console.WriteLine("IntQueue.Enqueue entered")
MyBase.Enqueue(obj)
End Sub

Public Overloads Sub Enqueue(ByVal obj As Object)
Throw New SystemException("IntQueue requires Integer parameter")
End Sub

Public Shadows Function Dequeue() As Integer
Console.WriteLine("IntQueue.Dequeue entered")
Return CInt(MyBase.Dequeue())
End Function
End Class

The disadvantage to this class is that the error only occurs at runtime.
The IDE doesn't ensure that the passed parameter is only integer.
Generally I will use encapsulation to create an IntQueue object, instead of
Inheritance, as you cannot change the types of the overriden types. Rarely
do you want to Shadow a method, as the result is rarely what you want. The
only place I (currently) use Shadows normally is when I have creating
derived controls and I need to change one of the Attributes on the
properties. I shadow the base property so I can add the attribute, however
the shadowed property does not attempt to change types, it simply calls the
base function. Overall the rule I use for Shadows is its use is the
exception not the norm!

Yes, that works as well. By using the Shadows I don't have to Shadow non
type-specific methods (like clear()). If I do it this way I have to mirror
all of the non type-specific methods as well so my class functions as a
full-blown queue.
Remember CInt & CType are conversion operators, while DirectCast is casting.
(CType will cast in some cases and convert in most cases, hence I use
DirectCast unless I have to use CType).

I apparently have a bit to learn about Casting and Conversion. I have been
thinking of them as the same which your statement implies is wrong
thinking.

I found this in the VB Language reference:
<quote>
The DirectCast keyword introduces a type conversion operation. You use it
the same way you use the CType keyword....

Both keywords take an expression to be converted as the first argument, and
the type to convert it to as the second argument. Both conversions fail if
there is no conversion defined between the data type of the expression and
the data type specified as the second argument.
The difference between the two keywords is that CType succeeds as long as
there is a valid conversion defined between the expression and the type,
whereas DirectCast requires the run-time type of an object variable to be
the same as the specified type. If the specified type and the run-time type
of the expression are the same, however, the run-time performance of
DirectCast is better than that of CType.

DirectCast is special in that conversions from type Object to any other
type are performed as a direct cast down the hierarchy — all of the special
conversion behaviors from Object are ignored.

</quote>

This last sentence is a bit unclear to me. I am not sure what "special
conversion behaviors" might be in an Object. Perhaps you can help?

I appreciate your taking the time to discuss this with me, Jay. I hope the
lurkers are learning as fast as I am.

Regards,
Ot
 
Ot,
I am getting what I want.
I suspect you are getting what you *think* you want. ;-) However! I suspect
you will eventually run into problems... :-(
Actually saying Dim aQ as Queue = New IntQueue would be a programming error
in my mind.
When you have the "Proverbial AHA!" on OOP then you will find that the above
is "preferred" in a number of cases. Especially when aQ is a class variable
or a parameter.To write fully general purpose routines you want to leverage
polymorphism and use the most base types for class variables & parameters,
this allows you to use that routine in the most cases. By routine I am
referring to both a single routine or a collection of routines represented
by a class.

Consider System.IO.Stream. Lets say I am creating a class that will convert
a DataSet to a stream & back in CSV (comma separated variable) format. If my
class accepts a Stream as a parameter, I am able to pass a FileStream to
read & write the DataSet in CSV format to a file. I am able to pass a
MemoryStream to read & write the DataSet in CSV format to the clipboard or
drag & drop. I am able to pass a NetworkStream to read & write the DataSet
in CSV format to a TCP connection. I am able to pass any class that derives
from Stream to support that category of Stream which may not have existed at
the time I wrote the CSV conversion class!

However if I based my class on FileStream I would be limited to just
operating on Files.

Using Shadows in IntQueue effectively limits you to IntQueue you cannot
reliably pass IntQueue to a class that accepts Queue as then you are using
the base methods, not your Shadowed methods... The base methods do not
ensure that the Queue itself only accepts integers...

Again I would recommend encapsulation over Shadows!

As an encapsulated based IntQueue does not inherit from Queue preventing you
from passing it to a routine that operates on Queues, possibly adding
non-integers to that queue!
I tried this and when I changed the Shadows keyword to Overrides the IDE
tell me
My sample was a standalone sample, there is NO integer Enqueue & Dequeue in
my sample!

The point of my sample was to show you that when you use Overrides (and
overrides only) that the derived versions of the functions are called, even
if your are using a base class variable (a Queue variable itself).

If you don't have it, you may want to purchase Robin A. Reynolds-Haertle's
book "OPP With Microsoft Visual Basic .NET and Microsoft visual C# .NET"
from MS Press. Robin does a very good job of explaining the "how to" of OOP
(overrides, overloads, shadows) in VB.NET.

Hope this helps
Jay
 
Jay,
I think I got a mini-"aha"! If I inherit from an existing class I can
broaden the functionality of the original class. In the particular example
we have been discussing I instead want to limit the functionality. The
"aha" is that it sunk in that IntQueue _is_ a Queue the way I have been
writing it.

If I take one of your suggestions and write an IntQueue that uses a Queue
object as a data store and simply give my class the functionality I want,
it accomplishes the goal of having a limited object that has only some of
the functionality of a queue.

Thank you for the reference to Reynolds-Haertle's book. I will certainly
read it.

Regards,
Ot

p.s. I am going to start a new thread regarding the distinction between
DirectCast and CType.
 
Back
Top