C# inheritance broken?

A

Andy

The code was:

class Employee { }
class VP extends Employee { }

Employee emp;
VP vp;

emp = new Employee();

vp = (VP)emp;

The book was Teach yourself Java 2 SDK 1.5 in 21 days from Sams and it
indicated code similar to the above would compile just fine.

Is that not the case? Or is there some detail that they didn't
mention at that point in the book?
 
J

Jon Skeet [C# MVP]

Yes, this makes sense. But System.Serialization doesn't allow this.
You cann't deserialize a stream into an already existing object.
Deserialization always creates a new object, and you can't assign the
newly deserialized object to 'this'.

Then you'll need to have something in the base class which allows you
to copy the data from an existing instance to a new one.

Think of serialization/deserialization as like dehydrating and
rehydrating vegetables - you wouldn't expect to dry out a carrot, then
rehydrate it and get a cauliflower!
 
J

Jon Skeet [C# MVP]

Andy said:
The code was:

class Employee { }
class VP extends Employee { }

Employee emp;
VP vp;

emp = new Employee();

vp = (VP)emp;

The book was Teach yourself Java 2 SDK 1.5 in 21 days from Sams and it
indicated code similar to the above would compile just fine.

Yes, it will compile fine, because the compiler doesn't look carefully
enough to see that emp is bound to just be an Employee, not a VP.

However, it will fail at runtime with a ClassCastException.
 
M

Mike Schilling

Jon Skeet said:
Yes, it will compile fine, because the compiler doesn't look carefully
enough to see that emp is bound to just be an Employee, not a VP.

However, it will fail at runtime with a ClassCastException.

And notice that exactly the same is true in C# (mod the name of the
exception).
 
R

Ravichandran J.V.

The Virtual constructor technique would allow this in C++, which you can
substitute with the Factory pattern in C#. There are some good examples
of the Factory pattern in C# on the web.

Or, you can also use a technique called Covariance in C# with the help
of delegates. More can be posted here if you are able to follow this far
and interested in using delegates in your code.

with regards,


J.V.Ravichandran
- http://www.geocities.com/
jvravichandran
- Or, just search on "J.V.Ravichandran"
at http://www.Google.com
 
J

Jon Skeet [C# MVP]

Ravichandran J.V. said:
The Virtual constructor technique would allow this in C++, which you can
substitute with the Factory pattern in C#. There are some good examples
of the Factory pattern in C# on the web.

Or, you can also use a technique called Covariance in C# with the help
of delegates. More can be posted here if you are able to follow this far
and interested in using delegates in your code.

I fail to see how delegates are relevant here...
 
R

Ravichandran J.V.

"Covariance permits a method with a derived return type to be used as
the delegate,..." (msdn)

"When a delegate method has a return type that is more derived than the
delegate signature, it is said to be covariant. " (msdn)

It is just a technique that can substitute the virtual constructor
technique. It is not as if delegates should not be suggested if the
topic is on inheritance, is it? In this context, delegates help in
achieving the kind of covariance that is desired.

with regards,


J.V.Ravichandran
- http://www.geocities.com/
jvravichandran
- Or, just search on "J.V.Ravichandran"
at http://www.Google.com
 
J

Jon Skeet [C# MVP]

"Covariance permits a method with a derived return type to be used as
the delegate,..." (msdn)
"When a delegate method has a return type that is more derived than the
delegate signature, it is said to be covariant. " (msdn)

Indeed. I know all this... but it's not relevant.
It is just a technique that can substitute the virtual constructor
technique. It is not as if delegates should not be suggested if the
topic is on inheritance, is it? In this context, delegates help in
achieving the kind of covariance that is desired.

The OP wants to use an instance of a base class as if it were an
instance of a derived class. I still fail to see how delegate
covariance is relevant - all it means is that if you could use a
delegate which specifies that it returns an instance of MyDocument as
if it's an instance of a delegate which specifies that it returns an
instance of Document. That's not at all the same as what the OP's
trying to do.

In particular, it in no way allows you to convert an object of one
type to another type.

Jon
 
G

groups

Jake Stevenson's posted an example earlier on this thread.

That's all fine, but it does not get around the cost of *copying* the
object.

I suppose that what I really want here is a sort of "reference"
constructor, something like the "Attach" method in ATL's CComPtr
class. Come to think of it, CComPtr actually "wraps" the interface
being used, but its wrapper is generated automatically by a
preprocessor. Too bad C# doesn't have an automatic wrapper generator
similar to the #import directive in C++!

Tony

Tom,

Do you have a an example of how to do this with reflection?

Mike Ober.



Reflection :)
 
M

Mike Schilling

Jake Stevenson's posted an example earlier on this thread.

That's all fine, but it does not get around the cost of *copying* the
object.

I suppose that what I really want here is a sort of "reference"
constructor, something like the "Attach" method in ATL's CComPtr
class. Come to think of it, CComPtr actually "wraps" the interface
being used, but its wrapper is generated automatically by a
preprocessor. Too bad C# doesn't have an automatic wrapper generator
similar to the #import directive in C++!

What bastard variant of C++ has an "#import" directive?
 
G

groups

Usage of #import:

#import <filename.ocx>

Just typing this line in Visual Studio will generate a .h and a .cpp
file wrapping all of the methods and properties of an OCX control.
 
A

Andre Kaufmann

Mike said:
[...]
But you haven't shown a C++ solution either, since the cast in your example
doesn't work.

If a constructor is added like in the following example, it will work.
Think that was the intention of Tony.

class Document
{
public:
Document(){}
static Document Load() { return Document(); }
};

class MyDocument : public Document
{
public:
MyDocument() {}
MyDocument(Document& s) : Document(s) {}
static MyDocument Load() { return Document::Load(); }
};

int main(int argc, char* argv[])
{
MyDocument s = MyDocument::Load();
return 0;
}

Andre
 
A

Andre Kaufmann

Jake Stevenson's posted an example earlier on this thread.

[...]

preprocessor. Too bad C# doesn't have an automatic wrapper generator
similar to the #import directive in C++!

It should have one, since it will generate a Interop DLL if you add a
COM dll reference. But why don't you automatically write and let a small
program do you this for you via reflection ? Should be fairly simple to
generate a MyDocument class with all the methods of Document
implemented, which all are delegating the call to an internal Document
object ?

By the way a object holding more than 100 methods, is IMHO somewhat
overloaded with methods - but that's another story.

Andre
 
G

groups

Andre,

That's great for C++. But in C# you can't set "base" in a
constructor.

Tony

Mike said:
[...]
But you haven't shown a C++ solution either, since the cast in your example
doesn't work.

If a constructor is added like in the following example, it will work.
Think that was the intention of Tony.

class Document
{
public:
Document(){}
static Document Load() { return Document(); }

};

class MyDocument : public Document
{
public:
MyDocument() {}
MyDocument(Document& s) : Document(s) {}
static MyDocument Load() { return Document::Load(); }

};

int main(int argc, char* argv[])
{
MyDocument s = MyDocument::Load();
return 0;

}

Andre
 
G

groups

Reflection is no good, because of the amount of time it takes to make
a copy for a large document.

BTW, you'll find lots of properties and methods, buried many layers
deep, in IWebBrowser and IHtmlDocument also.

Tony

Jake Stevenson's posted an example earlier on this thread.

preprocessor. Too bad C# doesn't have an automatic wrapper generator
similar to the #import directive in C++!

It should have one, since it will generate a Interop DLL if you add a
COM dll reference. But why don't you automatically write and let a small
program do you this for you via reflection ? Should be fairly simple to
generate a MyDocument class with all the methods of Document
implemented, which all are delegating the call to an internal Document
object ?

By the way a object holding more than 100 methods, is IMHO somewhat
overloaded with methods - but that's another story.

Andre
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

|> No, it's simply bad design of the base class, or trying to made a bad use
of
| > the class.
|
| You say the base class is designed poorly. So what would a GOOD
| design look like? The constraints are:
| - Original 'Document' object has been serialized as a 'Document.'
| - Reflection (to make a copy) is impractical because it is time-
| intensive.
| - Wrapping (MyDocument "contains" a Document" is impractical because
| of the large numbers of methods that would have to be reproduced.

What about:

class D{

public D( string file ) { LoadDoc(file); }
protected virtual void LoadDoc( string file ) {}
}

class D1:D
{
public D1( string file ):base(file){}
protected override void LoadDoc( string file )
{
base.LoadDoc();
// my stuff
}

public static D1 GetD1( string file ){ return new D1( file ); }

}

You then can do D1.GetD1( file) and get a D1
 
G

groups

Ignacio,

That would work great, except that serialization (used by LoadDoc to
read the document from a file) does not load a new object into "this"
or "base". It always creates a new object of whatever type was
originally serialized, in this case, a Document object. This new
Document object cannot be cast to a MyDocument, nor can it be assigned
to "this" or "base", because these are always read-only.

Tony
 
A

Andre Kaufmann

Andre,

That's great for C++. But in C# you can't set "base" in a
constructor.

Was only a valid sample of how to do it in C++. In C# surely you can't
do this.

Andre
 

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