Casting base class to inherited one

J

jan.loucka

Hi,
We're building a mapping application and inside we're using open
source dll called MapServer. This dll uses object model that has quite
a few classes. In our app we however need to little bit modify come of
the classes so they match our purpose better - mostly add a few
methods etc.
Example: Open source lib has classes Map and Layer defined. The
relationship between them is one to many.
We created our own versions (inherited) of Map called OurMap and our
version of Layer called OurLayer. The only difference between them is
that they have some extra methods (because we need them to do little
bit extra).
Is there any way how can I convert the base class (either Map or
Layer) to our inherited one (OurMap or OurLayer)?
I know that implicit or explicit conversion operators don't work
between inherited and base class but I was just wondering if there is
another way how to do this or if there's something wrong with our
object design?
Thanks for any help
 
B

Bruce Wood

Hi,
We're building a mapping application and inside we're using open
source dll called MapServer. This dll uses object model that has quite
a few classes. In our app we however need to little bit modify come of
the classes so they match our purpose better - mostly add a few
methods etc.
Example: Open source lib has classes Map and Layer defined. The
relationship between them is one to many.
We created our own versions (inherited) of Map called OurMap and our
version of Layer called OurLayer. The only difference between them is
that they have some extra methods (because we need them to do little
bit extra).
Is there any way how can I convert the base class (either Map or
Layer) to our inherited one (OurMap or OurLayer)?
I know that implicit or explicit conversion operators don't work
between inherited and base class

Who told you that? It's certainly not true. C# allows you to write
your own conversion operator, either implicit or explicit, that copies
the members from your base class object into a new, derived class
object, and return the derived object.

The only hitch, of course, is that you end up with a copy, but there's
no way around that.
 
J

jan.loucka

Who told you that? It's certainly not true. C# allows you to write
your own conversion operator, either implicit or explicit, that copies
the members from your base class object into a new, derived class
object, and return the derived object.

The only hitch, of course, is that you end up with a copy, but there's
no way around that.

When I try that the compiler complains:
C:\MapServer\IntraMaps60\SpatialEngineWS\Layers
\IntraMapsLayer.cs(208): 'DMS.IntraMaps.IntraMapsLayer.implicit
operator DMS.IntraMaps.IntraMapsLayer(layerObj)': user-defined
conversion to/from base class
I googled it and I found some articles that you cannot implicitly
convert from base class to it's child.
Am I doing something wrong?
 
B

Bruce Wood

When I try that the compiler complains:
C:\MapServer\IntraMaps60\SpatialEngineWS\Layers
\IntraMapsLayer.cs(208): 'DMS.IntraMaps.IntraMapsLayer.implicit
operator DMS.IntraMaps.IntraMapsLayer(layerObj)': user-defined
conversion to/from base class
I googled it and I found some articles that you cannot implicitly
convert from base class to it's child.
Am I doing something wrong?

Could you post the code you wrote? Both your definition of the
implicit conversion operator and your use of it?
 
B

Bruce Wood

Could you post the code you wrote? Both your definition of the
implicit conversion operator and your use of it?

Forget it. I just read the C# spec on line, here:

http://msdn2.microsoft.com/en-us/library/aa664464(VS.71).aspx

It says quite clearly that I'm wrong: you cannot provide implicit or
explicit conversions either up or down the class hierarchy.

Which means that the only option left open to you is a copy
constructor: your derived class must have a constructor that accepts a
member of your base class, like this:

public class Derived : Base
{
public Derived(Base baseObject)
{
...
}
}

or, you could make it a static method in your derived class:

public static Derived DerivedFromBase(Base baseObject) { ... }

Bummer about the conversions, though. I guess it causes some sort of
problem within the CLR....
 
J

jan.loucka

Could you post the code you wrote? Both your definition of the
implicit conversion operator and your use of it?

This is my inherited class:

public class IntraMapsLayer : layerObj
{
public IntraMapsLayer(superMapObj map) : base (map)
{
this.currentSuperMapObj = map;
}

public static implicit operator IntraMapsLayer(layerObj layer)
{
IntraMapsLayer newLayer = new IntraMapsLayer(this.map);
newLayer.bandsitem = layer.bandsitem;
newLayer.classitem = layer.classitem;
newLayer.connection = layer.connection;
newLayer.connectiontype = layer.connectiontype;
newLayer.data = layer.data;
newLayer.debug = layer.debug;
newLayer.dump = layer.dump;
//newLayer.extent = layer.extent;
newLayer.filteritem = layer.filteritem;
newLayer.footer = layer.footer;
newLayer.group = layer.group;
newLayer.header = layer.header;
//newLayer.index = layer.index;
newLayer.labelangleitem = layer.labelangleitem;
newLayer.labelcache = layer.labelcache;
newLayer.labelitem = layer.labelitem;
newLayer.labelmaxscale = layer.labelmaxscale;
newLayer.labelminscale = layer.labelminscale;
newLayer.labelrequires = layer.labelrequires;
newLayer.labelsizeitem = layer.labelsizeitem;
//newLayer.map = layer.map;
newLayer.maxfeatures = layer.maxfeatures;
newLayer.maxscale = layer.maxscale;
//newLayer.metadata = layer.metadata;
newLayer.minscale = layer.minscale;
newLayer.name = layer.name;
//newLayer.numclasses = layer.numclasses;
//newLayer.numitems = layer.numitems;
//newLayer.numjoins = layer.numjoins;
//newLayer.numprocessing = layer.numprocessing;
newLayer.offsite = layer.offsite;
newLayer.plugin_library = layer.plugin_library;
newLayer.plugin_library_original = layer.plugin_library_original;
newLayer.postlabelcache = layer.postlabelcache;
newLayer.requires = layer.requires;
newLayer.sizeunits = layer.sizeunits;
newLayer.status = layer.status;
newLayer.styleitem = layer.styleitem;
newLayer.symbolscale = layer.symbolscale;
newLayer.template = layer.template;
newLayer.tileindex = layer.tileindex;
newLayer.tileitem = layer.tileitem;
newLayer.tolerance = layer.tolerance;
newLayer.toleranceunits = layer.toleranceunits;
newLayer.transform = layer.transform;
newLayer.transparency = layer.transparency;
newLayer.type = layer.type;
newLayer.units = layer.units;
return newLayer;
}


this implicit operator does not even compile. I haven't mentioned it
yet but we're bound to .NET 1.1 unfortunatelly
 
S

Scott M.

Who told you that? It's certainly not true. C# allows you to write
your own conversion operator, either implicit or explicit, that copies
the members from your base class object into a new, derived class
object, and return the derived object.

So does VB .NET 2005.
 
J

jan.loucka

Forget it. I just read the C# spec on line, here:

http://msdn2.microsoft.com/en-us/library/aa664464(VS.71).aspx

It says quite clearly that I'm wrong: you cannot provide implicit or
explicit conversions either up or down the class hierarchy.

Which means that the only option left open to you is a copy
constructor: your derived class must have a constructor that accepts a
member of your base class, like this:

public class Derived : Base
{
public Derived(Base baseObject)
{
...
}

}

or, you could make it a static method in your derived class:

public static Derived DerivedFromBase(Base baseObject) { ... }

Bummer about the conversions, though. I guess it causes some sort of
problem within the CLR....

I didn't get what was the copy constructor supposed to do - can u
explain it to me?
 
G

G.Doten

This is my inherited class:

public class IntraMapsLayer : layerObj
{
public IntraMapsLayer(superMapObj map) : base (map)
{
this.currentSuperMapObj = map;
}

public static implicit operator IntraMapsLayer(layerObj layer)
{
IntraMapsLayer newLayer = new IntraMapsLayer(this.map);
newLayer.bandsitem = layer.bandsitem;
newLayer.classitem = layer.classitem;
newLayer.connection = layer.connection;
newLayer.connectiontype = layer.connectiontype;
newLayer.data = layer.data;
newLayer.debug = layer.debug;
newLayer.dump = layer.dump;
//newLayer.extent = layer.extent;
newLayer.filteritem = layer.filteritem;
newLayer.footer = layer.footer;
newLayer.group = layer.group;
newLayer.header = layer.header;
//newLayer.index = layer.index;
newLayer.labelangleitem = layer.labelangleitem;
newLayer.labelcache = layer.labelcache;
newLayer.labelitem = layer.labelitem;
newLayer.labelmaxscale = layer.labelmaxscale;
newLayer.labelminscale = layer.labelminscale;
newLayer.labelrequires = layer.labelrequires;
newLayer.labelsizeitem = layer.labelsizeitem;
//newLayer.map = layer.map;
newLayer.maxfeatures = layer.maxfeatures;
newLayer.maxscale = layer.maxscale;
//newLayer.metadata = layer.metadata;
newLayer.minscale = layer.minscale;
newLayer.name = layer.name;
//newLayer.numclasses = layer.numclasses;
//newLayer.numitems = layer.numitems;
//newLayer.numjoins = layer.numjoins;
//newLayer.numprocessing = layer.numprocessing;
newLayer.offsite = layer.offsite;
newLayer.plugin_library = layer.plugin_library;
newLayer.plugin_library_original = layer.plugin_library_original;
newLayer.postlabelcache = layer.postlabelcache;
newLayer.requires = layer.requires;
newLayer.sizeunits = layer.sizeunits;
newLayer.status = layer.status;
newLayer.styleitem = layer.styleitem;
newLayer.symbolscale = layer.symbolscale;
newLayer.template = layer.template;
newLayer.tileindex = layer.tileindex;
newLayer.tileitem = layer.tileitem;
newLayer.tolerance = layer.tolerance;
newLayer.toleranceunits = layer.toleranceunits;
newLayer.transform = layer.transform;
newLayer.transparency = layer.transparency;
newLayer.type = layer.type;
newLayer.units = layer.units;
return newLayer;
}


this implicit operator does not even compile. I haven't mentioned it
yet but we're bound to .NET 1.1 unfortunatelly

Have you tried this:

return (IntraMapsLayer)newLayer;

And why not go OO? There really is no need for the copy constructor and
the implicit conversion operator you are attempting to write. It just
makes for extra code that you'll then have to debug and maintain. And I
don't understand the purpose of the currentSuperMapObj since that is you
(IntraMapsLayer)!

public class IntraMapsLayer : layerObj // why is this call "Obj"
// do you really have a class
// called layerObj?
int _i1, _i2;
{
public IntraMapsLayer(int i1, int i2) : base (map)
{
_i1 = i1;
_i2 = i2;
}
}

IntraMapsLayer layer1 = new layerObj(1, 2);

The constructor then only needs to deals with any fields in the
IntraMapsLayer that are not in the base class. You can then up-cast if
you want:

layerObj layer2 = (IntraMapsLayer)layer1;

so that you can get at the fields specific to the layerObj class.

HTH
 
J

jan.loucka

Have you tried this:

return (IntraMapsLayer)newLayer;

And why not go OO? There really is no need for the copy constructor and
the implicit conversion operator you are attempting to write. It just
makes for extra code that you'll then have to debug and maintain. And I
don't understand the purpose of the currentSuperMapObj since that is you
(IntraMapsLayer)!

public class IntraMapsLayer : layerObj // why is this call "Obj"
// do you really have a class
// called layerObj?
int _i1, _i2;
{
public IntraMapsLayer(int i1, int i2) : base (map)
{
_i1 = i1;
_i2 = i2;
}

}

IntraMapsLayer layer1 = new layerObj(1, 2);

The constructor then only needs to deals with any fields in the
IntraMapsLayer that are not in the base class. You can then up-cast if
you want:

layerObj layer2 = (IntraMapsLayer)layer1;

so that you can get at the fields specific to the layerObj class.

HTH

as I described in my first email - we actually have a class called
layerObj. It comes from open source dll so we cannot change it. We
need to add some extra functionality to it - we did that by creating
derived class called IntraMapsLayer thus public class IntraMapsLayer :
layerObj

Whenever you do this - your implicit conversion operator:
(IntraMapsLayer) layer1 would not work!! You can try it but that is
what this topic is about. You cannot do that. At firts - you have to
write your own implicit conversion operator to do this. And second you
cannot write this conversion operator because you're trying to convert
base class to it's child. .NET doesn't allow that.
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

Hi,
We're building a mapping application and inside we're using open
source dll called MapServer. This dll uses object model that has quite
a few classes. In our app we however need to little bit modify come of
the classes so they match our purpose better - mostly add a few
methods etc.
Example: Open source lib has classes Map and Layer defined. The
relationship between them is one to many.
We created our own versions (inherited) of Map called OurMap and our
version of Layer called OurLayer. The only difference between them is
that they have some extra methods (because we need them to do little
bit extra).
Is there any way how can I convert the base class (either Map or
Layer) to our inherited one (OurMap or OurLayer)?
I know that implicit or explicit conversion operators don't work
between inherited and base class but I was just wondering if there is
another way how to do this or if there's something wrong with our
object design?
Thanks for any help

I would suggest encapsulation instead of inheritance.

Put the Map instance as a member in the OurMap class. You can provide
methods that call the methods in the Map class, but if there are a lot
of methods you might want to expose the Map object as a property instead.
 
G

G.Doten

as I described in my first email - we actually have a class called
layerObj. It comes from open source dll so we cannot change it. We
need to add some extra functionality to it - we did that by creating
derived class called IntraMapsLayer thus public class IntraMapsLayer :
layerObj

Sure, but I'm not proposing you change the layerObj class (one reason is
that you can't and the other reason is that it is not OO). I'm proposing
that you inherit a new class from it, in which case you pick up all the
functionality of layerObj and can extend that functionality in you
subclass. It also means you don't have to have any kind of copy
constructor (which in this case would just waste execution time and
space). That's not what you appear to be doing in the code you posted
but it is what I am doing in the code that I posted. If I can help
clarify the code I posted, just let me know.
Whenever you do this - your implicit conversion operator:
(IntraMapsLayer) layer1 would not work!! You can try it but that is
what this topic is about. You cannot do that. At firts - you have to
write your own implicit conversion operator to do this. And second you
cannot write this conversion operator because you're trying to convert
base class to it's child. .NET doesn't allow that.

But I didn't create an implicit conversion operator. I create a class
(IntraMapsLayer) that subclasses another class (layerObj). So now there
are two distinct types, albeit tightly related. You can do this:

layerObj l1 = new layerObj(3, 4);
IntraMapsLayer l2 = new IntraMapsLayer(1, 2);
layerObj l3 = new IntraMapsLaer(1, 2);
layerObj l4 = (IntraMapsLaer)l3;

- l1 can only access members of the base class layerObj that has been
supplied by your vendor. The code for layerObj has not been changed in
any way.

- l2 can access not only the members of the base class layerObj but also
any members you have extended that class with in your IntraMapsLayerclass.

- l3 can only access the members of your layerObj class, even though
it's base class is the vendor-supplied layerObj class it is typed as a
layerObj.

- But l3 can be up-casted, for example see l4, in which l4 (which refers
to the same object as l3 does) can now access members of both the base
class and your class that derives from it.

* * *

BTW, I goofed in my code and this line:

public IntraMapsLayer(int i1, int i2) : base (map)

should read:

public IntraMapsLayer(int i1, int i2) : base (3, 4)

In other words, the constructor(s) for your new class must pass the
appropriate parameters to the base class.

* * *

Are you sure that IntraMapsLayer is not the name of the class that your
vendor has supplied to you and that layerObj is the name of class that
you have created and are attempted to dervice from IntraMapsLayer? The
names sure imply that to me.
 
G

G.Doten

Göran Andersson said:
I would suggest encapsulation instead of inheritance.

That would certainly work, but wouldn't it needlessly duplicate the
amount of memory needed and require copy constructors and implicit
conversion operators (looks to be not a trivial amount of code in this
cas) as opposed to simply inheriting from the vendor's class?
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

G.Doten said:
That would certainly work, but wouldn't it needlessly duplicate the
amount of memory needed and require copy constructors and implicit
conversion operators (looks to be not a trivial amount of code in this
cas) as opposed to simply inheriting from the vendor's class?

No, your class would just contain a reference to the Map object, not a
copy of it.

If your class doesn't add any data, it would only contain that
reference, and the constructor would just take a reference to the Map
object and put it in the reference:

public class OurMap {

private Map _map;

public OurMap(Map map) {
_map = map;
}

public Map Map { get { return _map; } }

... and your own methods

}

When you want an OurMap object from a Map object, just create one:

OurMap our = new OurMap(theMap);

To access the methods in the Map class, just use the Map property:

our.Map.SomeOriginalMethod();
 
G

G.Doten

Göran Andersson said:
No, your class would just contain a reference to the Map object, not a
copy of it.

Right, my mistake.
If your class doesn't add any data, it would only contain that
reference, and the constructor would just take a reference to the Map
object and put it in the reference:

public class OurMap {

private Map _map;

public OurMap(Map map) {
_map = map;
}

public Map Map { get { return _map; } }

... and your own methods

}

When you want an OurMap object from a Map object, just create one:

OurMap our = new OurMap(theMap);

To access the methods in the Map class, just use the Map property:

our.Map.SomeOriginalMethod();

Yeah, I get all that. But the OP wants to inherit from this class and
extend it. So I still think doing that is the best approach and was make
it unnecessary for the OP to write all that copy code. If they didn't
want to extend that class I would agree that encapsulation would be a
good idea, like you say.
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

G.Doten said:
Yeah, I get all that. But the OP wants to inherit from this class and
extend it. So I still think doing that is the best approach and was make
it unnecessary for the OP to write all that copy code. If they didn't
want to extend that class I would agree that encapsulation would be a
good idea, like you say.

But he also wants to get an OwnMap object from a Map object, and using
inheritance that is not possible without creating a new OwnMap object
and copy everything from the existing Map object to the new object.

So, there is no simple way of doing what the OP wants. It's either a lot
of work using inheritence, or using encapsulation which doesn't do it
exactly the way that the OP requested, but is easier to implement. It
just comes down to prioritising. :)
 
G

G.Doten

Göran Andersson said:
But he also wants to get an OwnMap object from a Map object, and using
inheritance that is not possible without creating a new OwnMap object
and copy everything from the existing Map object to the new object.

Do you mean the OurMap in the original post he made? That's a different
discussion. The OP switched over to a whole different set of class names
and provided sample code of what he was trying to do, and that's what I
was replying to. I see that this sub-thread is back to talking about
Map/OurMap and Layer/OurLayer. Sorry about the confusion; I wasn't
paying attention. FWIW, encapsulation, as you have already explained, is
a great solution to the original topic.
So, there is no simple way of doing what the OP wants. It's either a lot
of work using inheritence, or using encapsulation which doesn't do it
exactly the way that the OP requested, but is easier to implement. It
just comes down to prioritising. :)

For his IntraMapsLayer class that he is subclassing the layerObj with,
and the functionality he has said he would like for those, I believe
inheritance to be the easiest way to do that. (Again, but not for the
Map/OutMap requirements.)
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

G.Doten said:
Do you mean the OurMap in the original post he made?

Yes. I replied to the original post.
That's a different
discussion. The OP switched over to a whole different set of class names
and provided sample code of what he was trying to do, and that's what I
was replying to.

But I didn't reply to your reply. :)
 
J

jan.loucka

Sure, but I'm not proposing you change the layerObj class (one reason is
that you can't and the other reason is that it is not OO). I'm proposing
that you inherit a new class from it, in which case you pick up all the
functionality of layerObj and can extend that functionality in you
subclass. It also means you don't have to have any kind of copy
constructor (which in this case would just waste execution time and
space). That's not what you appear to be doing in the code you posted
but it is what I am doing in the code that I posted. If I can help
clarify the code I posted, just let me know.


But I didn't create an implicit conversion operator. I create a class
(IntraMapsLayer) that subclasses another class (layerObj). So now there
are two distinct types, albeit tightly related. You can do this:

layerObj l1 = new layerObj(3, 4);
IntraMapsLayer l2 = new IntraMapsLayer(1, 2);
layerObj l3 = new IntraMapsLaer(1, 2);
layerObj l4 = (IntraMapsLaer)l3;

- l1 can only access members of the base class layerObj that has been
supplied by your vendor. The code for layerObj has not been changed in
any way.

- l2 can access not only the members of the base class layerObj but also
any members you have extended that class with in your IntraMapsLayerclass.

- l3 can only access the members of your layerObj class, even though
it's base class is the vendor-supplied layerObj class it is typed as a
layerObj.

- But l3 can be up-casted, for example see l4, in which l4 (which refers
to the same object as l3 does) can now access members of both the base
class and your class that derives from it.

* * *

BTW, I goofed in my code and this line:

public IntraMapsLayer(int i1, int i2) : base (map)

should read:

public IntraMapsLayer(int i1, int i2) : base (3, 4)

In other words, the constructor(s) for your new class must pass the
appropriate parameters to the base class.

* * *

Are you sure that IntraMapsLayer is not the name of the class that your
vendor has supplied to you and that layerObj is the name of class that
you have created and are attempted to dervice from IntraMapsLayer? The
names sure imply that to me.

Thanks for all your replies - it developed into quite an interesting
discussion. I should probably step back a little bit and try to
properly explain what I'm actually trying to do.
Object model that we have from third party vendor:
mapObj - map object
layerObj - layer object

we want to add some funtionality to both of these so we created:
IntraMapsMap : mapObj
IntraMapsLayer : layerObj

now the fun starts when the third party code creates mapObj instance,
puts some layerObj instances into it (let's say 20 layers) and we
create 2 IntraMapsLayer instances and put them into this mapObj
instance as well (we can do that - mapObj accepts children of layerObj
as well). We have a method to get the layerObj from map object. We
want to be able to get a layerObj instance from mapObj instance and be
able to use some of the functionality of the IntraMapsLayer on it!
That means - we haven't created this instance of layerObj, it's
layerObj object and we want to somehow convert it to IntraMapsLayer.
Objectwise it's possible - they have the same data, just few extra
methods that we want to use. How can I do this?
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

Thanks for all your replies - it developed into quite an interesting
discussion. I should probably step back a little bit and try to
properly explain what I'm actually trying to do.
Object model that we have from third party vendor:
mapObj - map object
layerObj - layer object

we want to add some funtionality to both of these so we created:
IntraMapsMap : mapObj
IntraMapsLayer : layerObj

now the fun starts when the third party code creates mapObj instance,
puts some layerObj instances into it (let's say 20 layers) and we
create 2 IntraMapsLayer instances and put them into this mapObj
instance as well (we can do that - mapObj accepts children of layerObj
as well). We have a method to get the layerObj from map object. We
want to be able to get a layerObj instance from mapObj instance and be
able to use some of the functionality of the IntraMapsLayer on it!
That means - we haven't created this instance of layerObj, it's
layerObj object and we want to somehow convert it to IntraMapsLayer.
Objectwise it's possible - they have the same data, just few extra
methods that we want to use. How can I do this?

You can't do that. You would have to create a new IntraMapsLayer object
and copy all the data from the layerObj object into it.

I once again suggest encapsulation instead of inheritance. Then you can
easily create an IntraMapsLayer object around an existing layerObj object.
 

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