简体   繁体   中英

How should I call a base class constructor with a class derived from a generic base class?

I have a generic class Grid which contains Cell s. My plan is to create several derived classes for Grid (TriangleGrid, SquareGrid, HexGrid) and Cell (TriangleCell, SquareCell, HexCell). Each Grid will have a GetAdjacentCells method.

abstract public class Grid<T> where T:Cell {
  protected T[,] cells_;
  abstract public List<T> GetAdjacentCells(T cell);
}

abstract public class Cell {
  protected Grid<Cell> grid_;
  public Cell(Grid<Cell> grid, int x, int y) {
    grid_ = grid;
  }
}

The HexGrid derived classes:

public class HexGrid : Grid<HexCell> {}

and

public class HexCell : Cell {
  public HexCell(HexGrid grid, int x, int y)
      : base(grid, x, y) { // compilation error here!
  }
}

Each Cell has a reference to its Grid , which is passed in through the Cell constructor. The issue I am facing is an error on the HexCell constructors call to base which says:

Error   CS1503  Argument 1: cannot convert from 'HexGrid' to 'Grid<Cell>'

HexGrid is a Grid<HexCell> and HexCell is derived from Cell so it seems like it should work.

I tried making Grid and Cell abstract. I tried casting the grid argument to (Grid<Cell>) which produced an error too. Any suggestions would great. Thanks!

I've tried a few approaches and failed. But then: Why do we need generics in this case at all? Consider this idea:

abstract public class Grid
{
    protected Cell[,] cells_;
    abstract public List<Cell> GetAdjacentCells(Cell cell);
}

abstract public class Cell
{
    protected Grid grid_;
    public Cell(Grid grid, int x, int y)
    {
        grid_ = grid;
    }
}

public class HexGrid : Grid
{
    public override List<Cell> GetAdjacentCells(Cell cell)
    {
        throw new NotImplementedException();
    }
}

There's nothing that needs to be generic here.

Since You have control over the cell too, make it be implementing an interface and then use that as 'contract' this way all derived ones or usages can be of this and you just have to promote necessary stuff to the interface though.

public interface ICell
{
    
}

abstract public class Grid<T> where T : ICell
{
    protected T[,] cells_;
    abstract public List<T> GetAdjacentCells(T cell);
}

abstract public class Cell : ICell
{
    protected Grid<ICell> grid_;
    public Cell(Grid<ICell> grid, int x, int y)
    {
        grid_ = grid;
    }
}

public class HexGrid : Grid<ICell>
{
    public override List<ICell> GetAdjacentCells(ICell cell)
    {
        throw new NotImplementedException();
    }
}

public class HexCell : Cell
{
    public HexCell(HexGrid grid, int x, int y)
        : base(grid, x, y)
    { 
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM