|
web
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Wrapper classesPublic 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 Moran wrote:
Show quoteHide quote >This may be a trivial question, but it's stumping me. If you only want a reference to A, then don't inherit A, just dim a > >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 > > 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--- -- Show quoteHide quoteHope this helps Jay B. Harlow [MVP - Outlook] ..NET Application Architect, Enthusiast, & Evangelist T.S. Bradley - http://www.tsbradley.net "Dave Moran" <dmoran@nospam.nospam> wrote in message news:3843E52B-EA7C-450E-97FC-25E8752220E5@microsoft.com... | 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. -- Show quoteHide quoteHope this helps Jay B. Harlow [MVP - Outlook] ..NET Application Architect, Enthusiast, & Evangelist T.S. Bradley - http://www.tsbradley.net "Dave Moran" <dmoran@nospam.nospam> wrote in message news:D8BBD789-854E-4876-AD66-B9C7F3A9E473@microsoft.com... | 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 |
FAST date string conversion ?
playing & re-playing 7 .wav files How To Force Copy One File To Another datagrid current record Possible to monitor changes in array (with event)? Debug.WriteLine Doesn't Produce Output Problems with URL Syntax Raising Events in Modules? Re: How to Use a Screen Saver app within My Application? word automation |
|||||||||||||||||||||||