Wrapper classes

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

This may be a trivial question, but it's stumping me.

Public Class A

End Class

Public Class B
Inherits A

Public Sub New B(ByRef a as A)
'I want this class to reference 'a' and not copy it.
End Sub
End Class

The idea is that you provide an instance of the base class 'A' and wrap
class 'B' around the same instance to provide extra functionality. I want to
specialise class 'A' into class 'B'. How do I do this?

Dave
 
Dave said:
This may be a trivial question, but it's stumping me.

Public Class A

End Class

Public Class B
Inherits A

Public Sub New B(ByRef a as A)
'I want this class to reference 'a' and not copy it.
End Sub
End Class

The idea is that you provide an instance of the base class 'A' and wrap
class 'B' around the same instance to provide extra functionality. I want to
specialise class 'A' into class 'B'. How do I do this?

Dave
If you only want a reference to A, then don't inherit A, just dim a
variable of type A, and assign it equal to a.
 
Dave,
ByRef & ByVal are how parameters are passed.

Class & Structure are how variables are stored.


Remember Class is a reference type, which means a variable of a Class type
holds a reference to the actual object. The object itself is on the heap.

Where as Structure & Enum are value types, which means a variable of a
Structure or Enum type holds the actual value. This variable could be
either on the stack in the case of parameters & local variables or on the
head in the case of member fields.

When you pass something ByRef you are passing a reference to the passed
variable. Whereas if you pass something ByVal you are passing a copy of the
passed variable.

Which means if you pass a variable of a Class type ByRef, you are passing a
reference to a reference to an object. Where as if you pass variable of a
Class type ByVal you are passing a copy of the reference to an object.

You should "only" use ByRef when you want the called routine to be able to
modify the passed variable itself. For example you want to return multiple
values from a routine.

That being said, you simply pass a class ByVal when you want to copy the
reference to the object on the heap.

For example, you would do something like:

Public Class A

Public Overridable Sub Something()

End Sub

End Class

Public Class B
Inherits A

Private ReadOnly m_wrapped As A

Public Sub New(ByVal a As A)
m_wrapped = a
End Sub

Public Overrides Sub Something()
m_wrapped.Something()
End Sub

End Class

Here is a more involved example:

---x--- cut here ---x--- begin TraceStream.vb ---x---
Option Strict On
Option Explicit On

Imports System.IO

Public Class TraceStream
Inherits Stream

Private ReadOnly m_stream As Stream

Public Sub New(ByVal stream As Stream)
If stream Is Nothing Then Throw New ArgumentNullException("stream")
m_stream = stream
End Sub

Private Sub WriteTrace(ByVal format As String, ByVal ParamArray args()
As Object)
Dim message As String = String.Format(format, args)
Trace.WriteLine(message, "TraceStream")
End Sub

Public Overrides ReadOnly Property CanRead() As Boolean
Get
Return m_stream.CanRead
End Get
End Property

Public Overrides ReadOnly Property CanSeek() As Boolean
Get
Return m_stream.CanSeek
End Get
End Property

Public Overrides ReadOnly Property CanWrite() As Boolean
Get
Return m_stream.CanWrite
End Get
End Property

Public Overrides ReadOnly Property Length() As Long
Get
Return m_stream.Length
End Get
End Property

Public Overrides Property Position() As Long
Get
Return m_stream.Position
End Get
Set(ByVal value As Long)
WriteTrace("Position={0}", value)
m_stream.Position = value
End Set
End Property

Public Overrides Sub Flush()
WriteTrace("Flush")
m_stream.Flush()
End Sub

Public Overrides Function Read(ByVal buffer() As Byte, ByVal offset As
Integer, ByVal count As Integer) As Integer
WriteTrace("Read(buffer={0}, offset={1}, count={2})", buffer,
offset, count)
Return m_stream.Read(buffer, offset, count)
End Function

Public Overrides Function Seek(ByVal offset As Long, ByVal origin As
System.IO.SeekOrigin) As Long
WriteTrace("Seek(offset={0}, origin={1})", offset, origin)
Return m_stream.Seek(offset, origin)
End Function

Public Overrides Sub SetLength(ByVal value As Long)
WriteTrace("SetLength(value={0})", value)
m_stream.SetLength(value)
End Sub

Public Overrides Sub Write(ByVal buffer() As Byte, ByVal offset As
Integer, ByVal count As Integer)
WriteTrace("Write(buffer={0}, offset={1}, count={2})", buffer,
offset, count)
m_stream.Write(buffer, offset, count)
End Sub

Public Overrides Sub WriteByte(ByVal value As Byte)
WriteTrace("WriteByte(value={0})", value)
m_stream.WriteByte(value)
End Sub

End Class
---x--- cut here ---x--- end TraceStream.vb ---x---



--
Hope this helps
Jay B. Harlow [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


| This may be a trivial question, but it's stumping me.
|
| Public Class A
|
| End Class
|
| Public Class B
| Inherits A
|
| Public Sub New B(ByRef a as A)
| 'I want this class to reference 'a' and not copy it.
| End Sub
| End Class
|
| The idea is that you provide an instance of the base class 'A' and wrap
| class 'B' around the same instance to provide extra functionality. I want
to
| specialise class 'A' into class 'B'. How do I do this?
|
| Dave
 
Hi Jay

Thanks very much for the detailed response. I've been on vacation and so
haven't been able to reply.

Your explanation makes sense to me, with one small exception. Why do I still
need to inherit from class A? Is this so class B appears to be derived from
class A?

If I wanted to add more specialization using class C, derived from class B,
is my example below correct? How do I handle creating an instance of class C
from an instance of class A? Should I cast it?

Thanks

Dave



Public Class A

Public Overridable Sub Something()

End Sub

End Class

Public Class B
Inherits A

Private ReadOnly m_wrappedA As A

Public Sub New(ByVal a As A)
m_wrappedA = a
End Sub

Public Overrides Sub Something()
m_wrappedA.Something()
End Sub

End Class

Public Class C
Inherits B

Private ReadOnly m_wrappedB As B

Public Sub New(ByVal a As A)
m_wrappedB = a 'What do I do here?
End Sub

Public Sub New(ByVal b As B)
m_wrappedB = b
End Sub

Public Overrides Sub Something()
m_wrappedB.Something()
End Sub

End Class
 
Hi Dave,

When B inherits from A, B is-a A. When B wraps A, B has-a A.

Actually your question is all about the classic Decorator design pattern.
You can find more info here:

#Decorator Design Pattern in C# and VB.NET
http://www.dofactory.com/Patterns/PatternDecorator.aspx

#.NET Matters: Stream Decorator
http://msdn.microsoft.com/msdnmag/issues/05/09/NETMatters/

Hope this helps. If anything is unclear, please feel free to post here.

Regards,
Walter Wang
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
Dave,
You don't per se:

However its what you are apparently asking for.

<quote>
The idea is that you provide an instance of the base class 'A' and wrap
class 'B' around the same instance to provide extra functionality. I want to
specialise class 'A' into class 'B'. How do I do this?
</quote>

"base class A" implies inheritance. "specialize class A" implies
inheritance. Now it may just be a case of nomenclature...


As Walter states, you use inheritance when you want B *is a* A. You use
wrapping (delegation) when B *has a* A.

You use both as I showed (and you are seemingly asking) when B is both *is
a* and *has a*, commonly a decorator. For example the TraceStream I showed
is a stream as it can be used any place a stream is used, plus it has a
stream as it operates on a second stream (the actual stream)...
BufferedStream does something similar.

Using both is an advanced topic.

--
Hope this helps
Jay B. Harlow [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


| Hi Jay
|
| Thanks very much for the detailed response. I've been on vacation and so
| haven't been able to reply.
|
| Your explanation makes sense to me, with one small exception. Why do I
still
| need to inherit from class A? Is this so class B appears to be derived
from
| class A?
|
| If I wanted to add more specialization using class C, derived from class
B,
| is my example below correct? How do I handle creating an instance of class
C
| from an instance of class A? Should I cast it?
|
| Thanks
|
| Dave
|
|
|
| Public Class A
|
| Public Overridable Sub Something()
|
| End Sub
|
| End Class
|
| Public Class B
| Inherits A
|
| Private ReadOnly m_wrappedA As A
|
| Public Sub New(ByVal a As A)
| m_wrappedA = a
| End Sub
|
| Public Overrides Sub Something()
| m_wrappedA.Something()
| End Sub
|
| End Class
|
| Public Class C
| Inherits B
|
| Private ReadOnly m_wrappedB As B
|
| Public Sub New(ByVal a As A)
| m_wrappedB = a 'What do I do here?
| End Sub
|
| Public Sub New(ByVal b As B)
| m_wrappedB = b
| End Sub
|
| Public Overrides Sub Something()
| m_wrappedB.Something()
| End Sub
|
| End Class
|
 
Back
Top