Inheritance design issue

M

Mark O'Flynn

I would like some advice regarding implementing inheritance using vb.net.

I have an application written in vb6 that I am rewritting from the ground up
in vb.net to take full advantage of .net, but I have encountered a design
issue implementing inheritance.

To explain my question, I will use an example. I have a Person class, with
properties such as ID, Name, Phone, Address etc. I then have a Manager
class that inherits Person and adds additional properties such as Division,
etc.

I load all the people from a database into an array list as part of a
Persons class.

Now, I want to load the Managers from a table that contains their ID, create
the Manager object with a reference to the Person data, and then load the
manager specific detail.

eg.

Dim oManager as New Manager
oManager = Persons.Find(ID:=1234)
oManager.Division = ...
....
Managers.Add(oManager)
MsgBox(oManager.Phone.ToString) ' Show phone number from the base Person
object

Now, this doesnt work as I get an invalid cast exception (as expected).

What I dont want is to create a new Manager, then load it with the data from
the Person Object

eg.

Dim oPerson as Person = Persons.Find(ID:=1234)
Dim oManager as New Manager
With oManager
.ID = oPerson.ID
.Name = oPerson.Name
...
.Division = ...
End With
MsgBox(oManager.Phone.ToString) ' Show phone number from the Manager object

If Phone is changed in the Person object, this will not be reflected in the
Manager object.

It seems to me that this would be a common situation faces in OOP, so any
advice on how I can get an inheritied object to maintain a reference to the
base object's data, or how best to design a solution would be most
appriciated.

Thanks in advance,

Mark O'Flynn
 
L

Lucas Tam

If Phone is changed in the Person object, this will not be reflected
in the Manager object.

It seems to me that this would be a common situation faces in OOP, so
any advice on how I can get an inheritied object to maintain a
reference to the base object's data, or how best to design a solution
would be most appriciated.


I think you'll want to declare your manager phone property as "Shadows"
phone. This allows you to create an identically named proprety called
phone which won't override the base class property:

Shadows
Optional. Indicates that this property shadows an identically named
programming element, or set of overloaded elements, in a base class. You
can shadow any kind of declared element with any other kind. If you
shadow a property with another property, the arguments and the return
type do not have to match those in the base class property. A shadowed
element is unavailable from within the derived class that shadows it,
unless the shadowing element is inaccessible, for example if it is
Private.
Note You cannot specify both Overloads and Shadows in the same
property declaration.

To access the bass class data you'll need to provide a property to
access the bass class object (i.e. GetParentObject which will return
Mybase) or provide a property to access the bass class property (i.e.
GetPersonPhone).

MyBase
The MyBase keyword behaves like an object variable referring to the base
class of the current instance of a class. MyBase is commonly used to
access base class members that are overridden or shadowed in a derived
class. In particular, MyBase.New is used to explicitly call a base class
constructor from a derived class constructor.

It is invalid to use MyBase to call MustOverride base methods.


These are just ideas on the top of my head... and are untested. Maybe
someone with more OO experience can provide a better solution.
 
L

Larry Serflaten

Mark O'Flynn said:
Dim oManager as New Manager
oManager = Persons.Find(ID:=1234)
oManager.Division = ...
...
Managers.Add(oManager)
MsgBox(oManager.Phone.ToString) ' Show phone number from the base Person
object

Now, this doesnt work as I get an invalid cast exception (as expected).

Where does it fall short? If Manager inherits from Person, then the Msgbox
should show the Phone number.

If it fails on Persons.Find() it may be because that function returns a Person
object instead of a manager object. If that is the case you might add a Shared
function (FromPerson) to the manager class to convert a person object to a
manager object, or you might overload your constructor to allow a person
object to initialize the new manager object.

The above were listed in my own order of preference....

HTH
LFS
 
R

Richard Myers

Where does it fall short? If Manager inherits from Person, then the Msgbox
should show the Phone number.
It falls short when Polymorphically using a manager as a Person. Change the managers phone number
using the design he has and it will not be reflected in the *Base* person and vice versa because
essentially
all he has done is create a shallow copy.
If it fails on Persons.Find() it may be because that function returns a Person
object instead of a manager object.

It fails because you cant use a widening conversion to convert a Person to a Manager.
A Person class has no concept of a Manager class because it is sub-Person.

Sometimes an author etc will talk about the OOP following real world objects. It might seem like a
natural
class heirarchy to have Manager descend from Person but sometimes this just turns out to be a real
world
illusion tht confuses the design concept. Sometime the distinct is better made with a simple
attribute/property.

What behavioural differences are there between Person and Manager?

Richard
 
N

Nak

Hi Richard,
Sometimes an author etc will talk about the OOP following real world
objects. It might seem like a
natural
class heirarchy to have Manager descend from Person but sometimes this
just turns out to be a real
world illusion tht confuses the design concept.

LOL! That's a statement and a half! I like it.

Nick.
 
R

Richard Myers

LOL! That's a statement and a half! I like it.

Nobody laughs when im trying to be funny..... and then everyone laughs when im being serious.
....What gives?

;)

Richard
 
L

Larry Serflaten

Richard Myers said:
It falls short when Polymorphically using a manager as a Person. Change the managers phone number
using the design he has and it will not be reflected in the *Base* person and vice versa because
essentially all he has done is create a shallow copy.

Evidently you it read a bit different than I:
I would like some advice regarding implementing inheritance using vb.net.
To explain my question, I will use an example. I have a Person class, with
properties such as ID, Name, Phone, Address etc. I then have a Manager
class that inherits Person and adds additional properties such as Division,
etc.

From that it appears Manager inherits from Person so every method and property
of Person should be available as methods and properties of the Manager object.

Where it got confused was:
Now, I want to load the Managers from a table that contains their ID, create
the Manager object with a reference to the Person data, and then load the
manager specific detail.

So is it better to use a Manager with an embedded Person object, or just
use the Manager object outright? I'd suggest he should be using the manager
objects instead of the person objects, for those people who are managers.

LFS
 
R

Richard Myers

Evidently you it read a bit different than I:

Yep. I took this statement
If Phone is changed in the Person object, this will not be reflected in the
Manager object.

to be his major concern. I wonder if his "Inheritence Design Issue" is whether he should be using
inheritence at all. Maybe the distinction is better made through interfaces?
So is it better to use a Manager with an embedded Person object, or just
use the Manager object outright? I'd suggest he should be using the manager
objects instead of the person objects, for those people who are managers.

Yeah totally. That is after all why you would create a Person\Manager distinction in the first
place.

Really i think we need more info to give better advice. Its the kind of thing you need to look at
his UML for; I mean can a manager also be managed and thus a Team Member as well?

If all you want is qik and dirty and this is just a tutorial application i'd go with Person as a
property
of Manager. Dead simple and allows a change in a disconnected Manager object to be reflected By Ref
to a Person in your tree/list and vice versa.

You could also look at creating property groups such as PersonContactNumbers/PersonContactAddress
that
are much less granular than a simple value type such as

Private phone as String

and so reduce the work in shunting Person data around if you find the Person object as a
property is not granular enough.

But if you want the *right* answer then i suspect this will just be the start of a very long thread.
Archictectural threads are however the most interesting.

Richard
 
C

Cor Ligthert

Mark,

When you want the full advantage of .Net, why do you than not use the
dataset.

When you find that not nice encapsulated, than you can go for a strongly
typed dataset, what you can generata or build yourself by inheriting the
dataset.

When you do it right than will your strongly typed dataset have all the
aspects from your classes you are now building, however have a better
connection with your database.

When I now read
I load all the people from a database into an array list as part of a
Persons class

Than I am a little bit suprised, it looks for me if you try to avoid all
benefits from .Net

Just my thought?

Cor
 
D

David

I would like some advice regarding implementing inheritance using vb.net.

I have an application written in vb6 that I am rewritting from the ground up
in vb.net to take full advantage of .net, but I have encountered a design
issue implementing inheritance.

Actually, you haven't :). And you're right, this is a fairly common
situation.

Your inheritance structure is fine here. What you really have is an
object creation problem, which stems from a common situation where the
database structure doesn't map to the class structure very well.

Your big mistake is creating a person object, and then trying to upgrade
that person into a manager. You don't want to do that, what you really
want to do is create a manager from the start.
To explain my question, I will use an example. I have a Person class, with
properties such as ID, Name, Phone, Address etc. I then have a Manager
class that inherits Person and adds additional properties such as Division,
etc.

I load all the people from a database into an array list as part of a
Persons class.

Now, I want to load the Managers from a table that contains their ID, create
the Manager object with a reference to the Person data, and then load the
manager specific detail.

Don't do it that way. Instead, load both tables from the database, then
have some sort of class or function, create either an ordinary person or
a manager, depending on whether you have manager data available. This
is usually called a Factory pattern, or object factory, or class
factory. It's a pretty common pattern, so it has a lot of names to
describe slightly different methods of implementation.

Something like (in pseudocode)...

Public Function CreatePeople(personTable, managerTable) As ArrayList
For each personRow in personTable
Dim managerRow as DataRow = managerTable.FindById(person.ID)

If Not manager Is Nothing then
_arrayList.Add(New Manager(personRow, managerRow))
Else
_arrayList.Add(New Person(personRow)
End If
Next
Return _arrayList
End Function

There's a lot of variations on this, depending on whether you really
want a managers collection, should managers appear in the persons
collection, are there other kinds of persons, etc.

But the basic point is simple: create each object as the appropriate
class. A person is NOT a manager, and so you shouldn't be creating a
person object when you really want a manager. And you should be
creating your objects at a point in time when you don't know what the
"true" class of that object is.
 
R

Richard Myers

<David>
<..>

I agree with all those points...except i dont see how you can say:
A person is NOT a manager, and so you shouldn't be creating a
person object when you really want a manager.

In his problem space a Manager might need to be a person....
or at least be personable.

For instance if he has a contact group. He may need to add several
different types
of people/roles to the group so in order to keep the contact group
interface
simple he may need a Person base class. He might be better off
combining the factory method with having all his people implement a Person
interface if he needs to group them in any way.

Go for interface based polymorphism rather than inheritence based.

Richard
 
N

Nak

Go for interface based polymorphism rather than inheritence based.

The perfect solution for his needs. Or even as a bodge why not just have an
enumerated type for a person class stating what type of person it is.

Public enum personType
OfficeJunior = 1
Skiv = 2
Manager = 4
BossesPet = 8
Boss = 16
End enum

Could even be a bitwise combination, I've certainly known of it in real
world examples!

Nick.
 
C

Cor Ligthert

Richard,

How many times did you already made code like this (this is just a sample as
you never would do it by the way)

\\\
Dim mycontrol As Control = ListView1
If TypeOf mycontrol Is ListView Then
DirectCast(mycontrol, ListView).MultiSelect = True
End If
///

The listview is a manager and the Control describes persons

Just as idea

Cor
 
D

David

<David>
<..>

I agree with all those points...except i dont see how you can say:


In his problem space a Manager might need to be a person....
or at least be personable.

Well, a manager IS-A person. It's the opposite that isn't true.

Looking back, perhaps I wasn't clear about that. I think the fact that
manager derives from person is fine. That's what I meant by saying that
there really wasn't an inheritance design problem here. In my example I
still envisioned Manager deriving from Person.
For instance if he has a contact group. He may need to add several
different types of people/roles to the group so in order to keep the
contact group interface simple he may need a Person base class. He
might be better off combining the factory method with having all his
people implement a Person interface if he needs to group them in any
way.

Go for interface based polymorphism rather than inheritence based.

Interface vs. inheritance is an interesting question, but doesn't
address the basic issue of the OP. You can't add an interface to an
object at runtime any easier than you can change the class of an object.
 
M

Mark O'Flynn

There has been a lot of advice ... thanks to all for your input. My
solution probably resides in a combination of advices.

At the core of my concern was that I expected I could use inheritance to
inherit the 'data' and the 'functionality'. That is, the manager inherits
the persons functions like CalculatePay, CalculateTimeOff etc, and also
inherit the data, like Name=Mark, Phone=12345 etc (not the property dec but
the referenced data) .

I don't want to implement a Person Interface in my Manager class as I have
to rewrite (copy/paste) the bodies of all functions and properties. The vb6
app worked this way and it has become a maintenance problem. There are many
classes that implemented the Person interface and each one had to copy the
same code to perform the same functions. Also, inheritance is giving me
some other advantages, so I would like to stay with it if I can.
Your inheritance structure is fine here. What you really have is an
object creation problem, which stems from a common situation where the
database structure doesn't map to the class structure very well.

This is correct. The database structure is infact text files used by
another legacy system, and it was not built to map to a class structured
application. This is one constraint that I have.

At this point I am leaning towards passing the Person object into the
Manager constructor. it means that I have to shadow the properties and
functions of the base class, but I can pass the execution to the base class
using mybase.calc.... etc

Anyway, now to implementing some of the suggestions.

Thanks to all for the help.

MOF
 

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

Similar Threads


Top