Wrapper class

  • 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
{
}

public class B : A
{
B(A a)
{
// I want this class to reference 'a' and not copy it.
}
}

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
 
the wrapper does this:

From: Dave Moran - view profile
Date: Thurs, May 25 2006 6:09 pm
Email: Dave Moran <[email protected]>
Groups: microsoft.public.dotnet.languages.csharp
Not yet ratedRating:
show options


Reply | Reply to Author | Forward | Print | Individual Message | Show
original | Report Abuse | Find messages by this author


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

public class A
{
public A(stirng ConnectionString) {...}
}


public class B
{
private A internalA;
public B(stirng ConnectionString)
{
internalA = new A(ConnectionString);
}
}

otherwise you do not wrap A. you subclass it

hope this helps
Galin Iliev[MCSD.NET]
www.galcho.com
 
In this case B isn't an A; it just behaves like one,

One solution here would be an interface IA (i.e. "I" and your original class
name) which defines the key properties etc; B then implements IA (B : IA),
and forwards / specialises the methods to the instance of A that it holds.

Marc
 
Thanks for the speedy reply. I think I'm trying to subclass A rather than
wrap it. I want to reference the original, not create a new instance of A.

What needs to happen in the constructor of B if want it to simply reference
A (i.e. subclass)? I also need to pass in an instance of A into the
constructor, not the data for A.

Dave

public class A
{
public A(string ConnectionString) {...}
}

public class B : A
{
public B(A a)
{
internalA = new A(ConnectionString);
}
}
 
Dave,

You can't do this. The reason is that A doesn't have the information
that is needed to make it into B. If that was the case, then you would be
able to do a direct cast.

It just doesn't make sense. It's like saying all apples are red,
therefore, all red things are apples. Apples are a specific subclass of red
things, the reverse is not true.

Applying that here, you are saying "all instances of B are instances of
A, therefore, all instances of A are instances of B", which obviously, can
not be.

You have no choice but to copy the values. You can not get that
instance of A to be treated like B.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Dave Moran said:
Thanks for the speedy reply. I think I'm trying to subclass A rather than
wrap it. I want to reference the original, not create a new instance of A.

What needs to happen in the constructor of B if want it to simply
reference
A (i.e. subclass)? I also need to pass in an instance of A into the
constructor, not the data for A.

Dave

public class A
{
public A(string ConnectionString) {...}
}

public class B : A
{
public B(A a)
{
internalA = new A(ConnectionString);
}
}

Galcho said:
the wrapper does this:

From: Dave Moran - view profile
Date: Thurs, May 25 2006 6:09 pm
Email: Dave Moran <[email protected]>
Groups: microsoft.public.dotnet.languages.csharp
Not yet ratedRating:
show options


Reply | Reply to Author | Forward | Print | Individual Message | Show
original | Report Abuse | Find messages by this author


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

public class A
{
public A(stirng ConnectionString) {...}
}


public class B
{
private A internalA;
public B(stirng ConnectionString)
{
internalA = new A(ConnectionString);
}
}

otherwise you do not wrap A. you subclass it

hope this helps
Galin Iliev[MCSD.NET]
www.galcho.com
 
There's no such thing as trivial!

I didn't think I was assuming all instances of A were instances of B. I was
only assuming that all instances of B were instances of A (i.e. derived from
A).

What I was trying to do was create a set of helper functions that operate on
an instance of 'A' that I know is a particular type of object. I don't want
to copy any data. I just want to operate on the data using specialised
functions. What approach would you suggest?

Dave
 
Well, given that spec, there is no need for B to even pretend to be an A or
an IA; it's just an object whose ctor accepts an A, and exposes some
methods...?

If you really mean to be able to use an instance of B as an instance of A,
then you can't do this with an existing A; inheritance means "is an", not
"has an"; "has an" is encapsulation, as shown below. When B : A, then the
"A" part of that *is intrisically fixed in the B* - you can't change it.
Encapsulation with interfaces is a route out of this, as this is then "looks
like" - so B : IA and A : IA - anything that accepts an IA can have either
an A or a B, and if you /know/ you have a B then you can use the extra
functions. This was in my previous post.

Encapsulation example (with neither inheritance nor interfaces):

public class A {}

public class B {
private readonly A _a;
public B (A a) {
_a = a;
}
public void DoSomething() {
a.DoSomethingElse();
a.DoSomethingOther();
}
}
 
Thanks for the reply. Your suggestion doesn't sound quite right for what I
need. The derived class was designed to provide additional functionality to
that which exists in the base class. Implementing an interface just means
that I have to foward the methods to the base class, a lot of work for no
gain?

Perhaps I'm the problem the wrong way round. I need to operate on certain
instances of class A that I know have specialised characteristics. I don't
want to copy the data from A, I just want to operate on it.

Dave
 
Hi

Encapsulation does look to be the right thing to do here. I'm assuming that
the assignment simply increments the 'reference count' on the instance of A
and allows me to reference the data directly. Removing the readonly keyword
would also allow me to change that data, if necessary?

Thanks for everybody's suggestions.

Dave
 
this seems like encapsulation would be the best bet .. but in more general
situations you should probably have a look at the proxy/decorator patterns
(both instance and non-instance) which also support polymorhism.

example:

proxy ...

public class Foo {
public virtual void Bar() {
//some code
}
}

public class FooProxy : Foo{
private readonly Foo m_Foo;
public override void Bar() {
//add some code here
m_Foo.Bar();
//or add some code here
}
private FooProxy(Foo _Foo) {
m_Foo = Foo;
}
}

the instance proxy being ..

public class FooProxy : Foo{
public override void Bar() {
//add some code here
base.Bar();
//or add some code here
}
}

These patterns are generally used when you are changing the behaviors of
methods (as opposed to defining helper methods as you added)

Cheers,

Greg Young
MVP - C#
 
The readonly keyword indicates that you can't change which A the
variable _a points to after it's set in the constructor. It doesn't
make any claims about whether you can change the state of the A
referenced by _a; you can still do that.

Just for your information, .NET doesn't use reference counting, it uses
mark-and-sweep garbage collection. The effect is the same, though:
referencing an existing object prevents it from being collected.
 
Basically, it can't be done. Note, I'm not saying the C# won't let you.
It CANNOT be done.(sort of a law of phyisics thing)

What you would like to do is:
A a = new A();
B b = new B(a);

Which would mean that both a & b, which different types, nevertheless
occupy the same space. Consider what would happen if we did this:
a = null;

Now, the A object which was held by a can now be garage collected, but
b *is* that object. Is b collected as well?
 
Agree with everything Bruce says.

Just so add: I made _a "readonly" as this feels natural (to me, at least)
for a class that is meant to wrap an instance of something. If I need to be
able to change the "a" in question, then yes: we could ditch the "readonly"
and add some accessors, but then I would also start asking questions about
thread safety - do we have to sync all access to _a, for instance in case
another thread swaps it mid-way through an operation on b...

Whenever writing a wrapper or facade, my instinct is to make the underlying
object readonly until I *know* I have a (genuine) need to do otherwise...
for instance, another alternative here would simply be to create a new
instance of B around the new A... which is more appropriate depends on the
usage.

Marc
 
...
Thanks for the speedy reply. I think I'm trying to
subclass A rather than wrap it. I want to reference
the original, not create a new instance of A.

Well, it's not possible to subclass instances, just classes...
What needs to happen in the constructor of B if want
it to simply reference A (i.e. subclass)? I also need
to pass in an instance of A into the
constructor, not the data for A.

Dave

public class A
{
public A(string ConnectionString) {...}
}

public class B : A
{
public B(A a)
{
internalA = new A(ConnectionString);
}
}

What you seem to be looking for is the "Decorator" pattern, extending an
object rather than a class. There are several articles on how to achieve
this, e.g.:

http://www.codeproject.com/csharp/csdespat_2.asp

The "best" way to achieve this, is to use the interfaces from the class you
want to decorate, and simply forward all calls to the instance, with or
without other enhancements.

interface IA
{
void InstanceMethod();
}

public class A
{
public A(string ConnectionString) {...}

public void InstanceMethod() {...}
}

public class B : IA
{
private A internalA = null;

public B(A a)
{
internalA = a;
// Do not use new, simply use the reference...
}

public void InstanceMethod()
{
a.InstanceMethod();
}


public void NewMethod()
{
// Do something else with a;
}
}
--------------------------------------------

You *could* make the B class a subclass of A, and try to ignore the
inherited fields, etc, but that will not function very well, unless all
methods and properties in A are declared "virtual" so you can *override*
them.

// Bjorn A
 
Back
Top