Inheritance Problem

J

Joshua Frank

I've got a design problem that the .net inheritance model will not let me
solve. I didn't like the built in serialization (for various reasons) so I
defined my own serialization approach. I wanted to define an interface
ISerializable, and classes that need serialization would implement this. So
I had a Job class for jobs my app needs to do:
Interface ISerializable
Sub Read()
Sub Write()
End Interface

Class Job
Implements ISerializable
....
End Class

BUT: I then inherited from Job:
Class MySpecificJob
Inherits Job
....
End Class

I wanted to have MySpecificJob implement ISerializable, and when called, it
would serialize itself and then serialize MyBase, but .net doesn't allow
this, saying: "Interface is already implemented by the base class" I think
the framework should clearly let you override the implementation in a
derived class, so that you can use interface based design in a situation
like this.

So then I tried defining a class:
Class Serializable
Sub Read()
Sub Write()
End Interface

Class Job
Inherits Serializable
....
End Class

This works well but breaks when I need to serialize a class that already
inherits from something else, because .net also doesn't let you inherit from
multiple classes.

I kludged around this, but I'd really like to get the right approach. Any
ideas much appreciated. Thanks.

Cheers,
Josh
--
Joshua Frank
Senior Systems Architect
Archimetrics, L.L.C.
"Add some SpArk to your stored procedure development."
(web) http://www.archimetrics.com
(email) mailto:[email protected]
(voice) (973) 727-1510
 
Q

Qiu Zhang

Hi, Joshua:
I didn't meet such problems when doing the similar thing, It works
very well.
Here is some code snip, hope it helps!

Qiu
Interface ISerializable

Sub Read()

End Interface

Class ClassBase

Implements ISerializable

Public Sub Read() _

Implements ISerializable.Read

Console.WriteLine("base")

End Sub

End Class

Class Class2

Inherits ClassBase

Public Shadows Sub Read()

MyBase.Read()

Console.WriteLine("sub")

End Sub

End Class
 
J

Joshua Frank

This doesn't really work. .net knows that Class2 implements ISerializable,
but Class2::Read doesn't get you ISerializable::Read. If you try this:

CType(MyClass2, IThing).Read()

you get the ClassBase version, not the Class2 version. But if you need to
know about Class2, then there's no point to using interfaces.

There needs to be something like
Class Derived
Overrides MyBase.IThing
....
End Class

or something like that.
 
J

Joshua Frank

Thanks. That works much better. But there's still a problem. The derived
class doesn't have to override the base class's implementation, so that it's
easy to forget that you need to do this. And it's easy to mess it up in
other ways, for instance if you add a read method with the wrong signature
and forget to specify Overrides, vb.net thinks you're enhancing the base
class with a totally different method.

I tried to make the base class specify that you have to override, but you
can't have an Overridable MustOverride method. There should be a specifier
that says something like use this implementation if calling the base class,
but force the derived class to implement an override if using the derived
class.

Any ideas on this one?

Thanks.

Cheers,
Josh
 
Q

Qiu Zhang

Right, I should use Overriable to mark the function in Base class, and use
Overrides in Sub Class.

Just came across and added the "shadows" as the compiler indicated, I should
have looked up this in MSDN.

Qiu
 
M

Michael Lang

To force a base class to override you mark it as abstract (C#), or
"MustOverride" (VB.NET)? When you do this the entire class must be made
abstract. You cannot create an instance of an abstract class. But you can
create a variable of the abstract type that is capable of holding an
instance of any type derived from it.

Do the derived classes really HAVE to implement "Read" and "Write". Maybe
they have nothing extra they need to serialize? They could just be adding
functionality, and not extra properties? I think the developers deriving
from your base class are intelligent enough to know when to override a given
function. Just make sure you document your class so they know. The only
time you should really make a method abstract is when there is no logical
implementation for the base class. If there is a default implementation
that makes sense, you should provide it.
 
J

Joshua Frank

In general, both base and derived types will serialize stuff, as in:
Class Base
Implements ISerializable
Public BaseData as String
End Class

Class Derived
Inherits Base

Public DerivedData as String
End Class

When you serialize Derived, you really need to preserve its data and its
base class data. What I really need, and don't see any reason why it can't
be done in the CLR, is some keyword that lets you serialize Base if you're a
Base and implement Read/Write, but specify that if you happen to be a
Derived, then you have to implement Read/Write also. The way you'd do this
would be
Sub Write()
MyBase.Write()
'now serialize our own data
End Sub

As you say, you can write that you're supposed to do this in the
documentation, but the language should help out.
 
J

Joshua Frank

There are certainly some things that you'd like derived class implementors
to do that you can't make them do, so you just have to document the rules
and hope they're following. But since the whole point of interface
inheritance is to guarantee that all inheritors follow the contract, in this
case I think the language should make it easier for Derived to do so.

The Eiffel project looks cool, but I think I'll stick with one big learning
curve at a time for now. I do wish we had multiple inheritance in VB
though. I understand the complexity, and would use it sparingly, but when I
want it I want it. Sigh...
 
M

Michael Lang

There is no way to do it now. Maybe you could request it. Try emailing
(e-mail address removed)

I still don't see why your Read method should have that keyword anyway.
Some derived class may add functionality without adding new properties, in
which case, what would it have to add to the serialization? The only thing
that would be different is the type name....

.... When you are serializing the base class, and you are sepcifying the
typename, don't use a hardcoded string, instead use GetType() on the current
object, and convert that into a string. If it is a derived type, GetType
will return the derived type.

You can't do anything to enforce your class is derived from "properly". For
example you can't even make sure they call your base class version in the
overridden version, as you've shown in every example. If you are that
concered that people will use it wrong, then "seal" your class and don't let
them derive from it. Make them implement the interface on their own. You
could also supply them with some static methods that do the common stuff.

In summary, .NET has all the capability of traditional Object Oriented
Programming (OOP) except for mutiple inheritance (MI). And if you need MI
use Eiffel.NET. People have done quite amazing things with the current OOP
techniques. There is a good way to design your application with the current
capabilities. The hard part is deciding how you will use these features in
your architecture. With the limited knowledge we have of your project we
can't give you the best solution.

Eiffel.NET:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/pdc_eiffel.asp
 

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