Fog Creek Software
Discussion Board




Welcome! and rules

Joel on Software

"Silly" Question of C# Newbie on Inheritance

I'm learning C# + .NET and decided to write minesweeper. First I've created two classes: Plot and Field. Field basically handles and array of Plot-s.

Both classes are UI neutral. So I've created a GraphicField:Field and GraphicPlot:Plot.

So here is my question, what is the best way to make derived GraphicField to use GraphicPlot instead of Plot during its manipulations (whole business logic is inside Plot class).

Should I pass the name of Plot derived class to GraphicField constructor? Should I define Plot as abstract or even make some kind of PlotInterface?

Did I make myself clear? :-) I'd be grateful for any clues, sure someone did it before. I'm looking for "best practise".

The WebSpeed Man
Friday, October 31, 2003

(a) Sure, Plot can be abstract.  For a one-off program, it'll work fine.  But if other classes can inherit from Plot and get passed to GraphicsField, you may be in trouble.

(b) In the GraphicsField constructor, make sure only a GraphicsPlot can be passes, and not a Plot.  This'll probably do what you want.  If there are any member functions that need a GraphicsPlot instead of a Plot, make sure they specify GraphicsPlot in the argument list.

(c) Runtime type checking (it'll work, but it's not the way it's "supposed" to b done).  If the type is wrong, toss an exception.  We know how JoS loves to discuss exceptions.

Ankur
Friday, October 31, 2003

Thank you, Ankur, lets see:

public class Plot
{
  public Plot (bool bMine)
    {
      ......
    }
}

public class Field
{
  protected Plot [,] field;
  public Field (int x,int y, int numMines)
  {
    field = new Plot[x,y];

    // create field and populate with mines
    for (....

    }
}

public class GraphicPlot:Plot
{
    Button plotButton;
    public GraphicPlot(bool bMine):base(bMine)
    {
      plotButton = new Button();
    }
 
    public x {
          set { plotButton.x = value;}
                }
}

public class GraphicField:Field
{

  Form mineField;
  public GraphicField(int x,int y, int numMines):base(x,y,numMines)
    {
      mineField = new Form();
      for (...)
          field[x,y].x=10;
 
    }
}



My code looks like something above. It seems that I lack the knowledge how to pass GraphicPlot class (not an object!) as a parameter to GraphicField during its initialization, so I could replace field array of plot to the field array of GraphicPlot.

Thank you for your patience!

The WebSpeed Man
Monday, November 03, 2003

You could try using a Factory class to construct the elements of your application, rather than referencing the classes directly.  So, you'd have a GraphicsFactory that manufacturers the Plot/Field instances for you, and keeps everything consistent.

Here's a reference:  http://www.exciton.cs.rice.edu/JavaResources/DesignPatterns/FactoryPattern.htm

There are many others.

flunky
Monday, November 03, 2003

Thank you for URL I get the "object factory" idea, but I wonder if there are a better solution. May be I have to inherit Field from Plot?

The WebSpeed Man
Tuesday, November 04, 2003

There's something called the "Liskov Substitution Principle" that you should always use in deciding whether or not to use inheritance.  Here's one link, google will give you a large number of others:

http://www.brent.worden.org/articles/2000/liskovSubstitutionPrinciple.html

In the case of the Plot and Field, they do not satisfy this principle, so I wouldn't do it.

An approach along this line, though, would be to put a "NewPlot" method on the Field class that returned an instance of the proper kind of Plot object

flunky
Tuesday, November 04, 2003

Thank you, flunky. Right now you filled a massive gap in my OOP design basics knowledge.

:-) - a smile of gratitude

The WebSpeed Man
Wednesday, November 05, 2003

*  Recent Topics

*  Fog Creek Home