The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

OOP confusion

Excuse the question - I'm not a programmer, just an interested amateur - but I'm having a conceptual problem with OOP.

I'm writing a custom TreeView class (in VB.Net, if it matters) which will have two sorts of nodes: categories and widgets.  Categories and widgets are fundamentally different things and have different methods, properties, etc.  So at present I have a class hierarchy that looks like:

CustomTreeView inherits TreeView

CategoryNode inherits TreeNode
WidgetNode inherits TreeNode

The question is this.  When I click on a node in the CustomTreeView, I need to be able to figure out whether what I have clicked on is a category or a widget.  At the moment, I have an interface CustomNode with one property (NodeType) which both CategoryNode and WidgetNode implement, which allows me to test which it is.  But then all the common code (e.g., removing nodes, renaming nodes) gets duplicated in two code paths with a big If statement.  That doesn't seem clever.  What's the "right" way to do this?
jb
Wednesday, October 25, 2006
 
 
you need a starter textbook on oop

the solution is to use classes with inheritance
the common code is in the parent class

even better would be to create a helper class to
do the common functions, and make it a member of
your 2 node classes so you don't have to use
inheritance

it's sad that you're learning OOP when it's such
a bad way to program
declarative proramming is better
Wednesday, October 25, 2006
 
 
Ok.

If I put the common code in a parent class, then don't I then have to go through some funny hoops to figure out which child class the object actually "is" and therefore what to do with it?

animal = New Animal

If animal.type = dog then
    Dim dog as Dog
    dog = animal
    dog.eatBone
else
if animal.type = cat then
    Dim cat as Cat
    cat = animal
    cat.purr
end if

I suppose I could still be thinking procedurally here.  It's what I'm used to.  (But I'm struggling with windows forms)
jb
Wednesday, October 25, 2006
 
 
Rather than doing this:

> animal = New Animal
>
> If animal.type = dog then
>    Dim dog as Dog
>    dog = animal
>    dog.eatBone
> else
> if animal.type = cat then
>    Dim cat as Cat
>    cat = animal
>    cat.purr
> end if

instead do something like the following:
  animal = GetAnimalFromSomewhere
  animal.PerformAction

You are then free to do the following in Dog:
  PerformAction()
  {
    eatBone
  }

and in Cat:
  PerformAction()
  {
    purr
  }
which will require a method PerformAction() in the base class, wither with a default implementation (perhaps lookCute) or else is abstract, requiring derived classes to implement themselves.

With apologies for mixing and matching all sorts of languages in the examples!
Colin Ross Send private email
Wednesday, October 25, 2006
 
 
I don't know what the VB.NET terminology is, but what Colin described is an abstract class. It specifies the functions (or methods) available, but leaves it up to the child classes to actually implement them.

In the event that Visual Basic doesn't support abstract classes, try reversing the focus. That is, instead of having CategoryNode call the addNode function, pass the CategoryNode as data, to the parent tree object's addNode function. (If I've understood your example correctly.)

Any code that's common to the CategoryNode and the WidgetNode probably should not be in those objects, but rather in the TreeView object, including the NodeType variable.

In other words, TreeView could consist of two arrays of objects, one for CategoryNodes, and one for WidgetNodes. To add a new CategoryNode, you call

TreeView.addNode( new TreeNode(), "Category" )

To call a function unique to CategoryNode, you'd do...

TreeView.CategoryArray[i].doCategoryFunction()

....such as...

TreeView.CategoryArray[x].addChildWidget( TreeView.WidgetArray[y] )

And so on.
TheDavid
Wednesday, October 25, 2006
 
 
I maybe missing the whole question here but I think you want to take a look at VB.Net "IsA" keyword.

The following is not VB but you will get the point...

if (mynode IsA CategoryNode)
{
  // do CategoryNode stuff
}
else if mynode IsA WigetNode)
{
  // do WigetNode stuff
}
TownDrunk
Wednesday, October 25, 2006
 
 
Yup, what you're doing is also called "polymorphism", and Colin has a nice example of how to apply it.

In effect, because you created an object as a 'dog' class, the run-time environment will make sure when you call

MyAnimal.MakeNoise()

That the 'dog' class MakeNoise method will be called, instead of the 'cat' class MakeNoise method.  Yet you can store a whole bunch of 'dog' and 'cat' objects in an 'animal' array, which doesn't have to care which type each one is.
AllanL5
Wednesday, October 25, 2006
 
 
Thanks, all.  It was the essential notion of an "abstract" class that I was missing - I thought I had to implement all members of a class.  I have just removed 30 lines of code without changing functionality.
jb
Thursday, October 26, 2006
 
 
There is no better feeling than removing code and getting the same results.  Certainly beats adding code and breaking everything!
Colin Ross Send private email
Thursday, October 26, 2006
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz