# Inheritance method question

If I have this base class

``````using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GridBase : MonoBehaviour {

public NodeBase node;
public NodeBase[,] grid;
[HideInInspector]
public int gridSizeX, gridSizeY;        // This this the number of the grid to generate nodes in
public bool displayGridGizmos;            // Toggle GizmoDraw
public Vector2 gridWorldSize;            // This the world size in WS, grid will fit itself in here depending on the nodeRadius
public float nodeRadius;                // Node radius we use to generate our grid sizes
public float nodeDiameter;                // Node diameter we use to generate our grid sizes

//
// Create Grid from any node inherated from NodeBase
public T[,] CreateGrid<T>(T node ) where T : NodeBase{

//
// Set Grid size based on node Diameter
gridSizeX = Mathf.RoundToInt(gridWorldSize.x/nodeDiameter);
gridSizeY = Mathf.RoundToInt(gridWorldSize.y/nodeDiameter);

//
// Create Grid with given size
grid = new T[gridSizeX, gridSizeY];

//
// Find worldBottomLeft
Vector3 worldBottomLeft = transform.position - Vector3.right * gridWorldSize.x / 2 - Vector3.forward * gridWorldSize.y / 2;

//
// Populate grid
for (int x = 0; x < gridSizeX; x++) {
for (int y = 0; y < gridSizeY; y++) {
Vector3 worldPoint = worldBottomLeft + Vector3.right * (x * nodeDiameter + nodeRadius) + Vector3.forward * (y * nodeDiameter + nodeRadius);
grid [x, y] = System.Activator.CreateInstance(typeof(T), worldPoint, x, y) as T; /*This comes at a performace cost */
}
}

//
// Return Grid
return grid;
}

//
// Return node in a given grid from a worldPosition
public T GetNodeFromWorldPoint<T>(T[,] gridIn, Vector3 worldPositionIn ) where T : INodeAttrGridable
{
//
// Convet the worldPosition into a percentage
float percentX = (worldPositionIn.x + gridWorldSize.x/2) / gridWorldSize.x;
float percentY = (worldPositionIn.z + gridWorldSize.y/2) / gridWorldSize.y;
percentX = Mathf.Clamp01(percentX);
percentY = Mathf.Clamp01(percentY);

//
// Convert percentage into index
int x = Mathf.RoundToInt((gridSizeX-1) * percentX);
int y = Mathf.RoundToInt((gridSizeY-1) * percentY);
return gridIn[x,y];
}

}
``````

and I create my grid of nodes

``````grid = CreateGrid<NodeBase> (nodeBase);
``````

I call GetNodeFromWorldPoint like so

``````NodeBase targetNode = grid.GetNodeFromWorldPoint( grid, vecWorldPos);
``````

… Is there a way not to change the method so that I dont have to pass the grid into the method, like this

``````NodeBase targetNode = grid.GetNodeFromWorldPoint( vecWorldPos);
``````

Thanks you

An inherited method must have the same parameters as input. That way any code that’s using it doesn’t need to know what child class it actually is - it can call the shared method identically no matter what. If you have Parent, ChildA, ChildB, and ChildC with Method(x,y), and then ChildD has Method(y), you couldn’t have code that is able to call Method while being agnostic to the actual type it’s being called on, which is the entire point of inheriting methods. If you’re changing the needed parameters, you’re not doing inheritance correctly. Or, probably more accurately, you’re actually just doing a different method. So that’s option 1: Just make it a different method, explicitly (and don’t inherit it at all).

You may also simply pass ‘null’ into the first parameter, and have the method ignore that. But, again, I suspect that what you’re trying to do here is, on a conceptual level, not actually inheritance.

Or put the generic constraint on the class itself so the grid, in its entirety, is bound to a specific NodeBase type. Then

``````public NodeBase[,] grid;
``````

can become

``````public T[,] grid;
``````

Thanks guys this is great
@ Kelso, just before I created this post I had my whole base class a genetic. Let me try it again and post the error I was seeing. Thanks heaps

Pretty much this. You can’t override a method and give it different parameters. But you can overload a method with different parameters. I commonly use overloads to provide default parameters when the default is slightly more complicated then can be achieved in the signature.

So my question might not have been clear, Im not wanting to change the signature per class or even overload. I want to change the base class method signature so I dont have to pass the grid as a parameter. I feel since this method is in the gridBase class it should know its type. KelsoMRK suggestion is more inline with what im trying to achieve. Sorry if this was not clear.

So making the class generic

``````public class GridBase<T> : MonoBehaviour {

//[HideInInspector]
public T node;
public T[,] grid;
``````

and changing my function to

``````    public T GetNodeFromWorldPoint<T>( Vector3 worldPositionIn ) where T : NodeBase
{
//
// Convet the worldPosition into a percentage
float percentX = (worldPositionIn.x + gridWorldSize.x/2) / gridWorldSize.x;
float percentY = (worldPositionIn.z + gridWorldSize.y/2) / gridWorldSize.y;
percentX = Mathf.Clamp01(percentX);
percentY = Mathf.Clamp01(percentY);

//
// Convert percentage into index
int x = Mathf.RoundToInt((gridSizeX-1) * percentX);
int y = Mathf.RoundToInt((gridSizeY-1) * percentY);

return grid[x,y]; ///// ERROR HERE ///// Cannot implicitly convert type
}
``````

I get this error on my return line “return grid[x,y];”. But im not converting my type

error CS0029: Cannot implicitly convert type `T [Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null -- /Assets/Scripts/GridScripts/GridBase.cs]' to `T [Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null – /Assets/Scripts/GridScripts/GridBase.cs]’

You’ll need to move all of the generic constraints to the class:

``````public class GridBase<T> : MonoBehaviour where T : NodeBase { ...
``````

And then don’t re-define the T in GetNodeFromWorldPoint:

``````public T GetNodeFromWorldPoint ( Vector3 worldPositionIn ) { ...
``````

Saying GetNodeFromWorldPoint introduces a new type variable T, which is different from the class’ type variable T. It’s the same thing as having a field named “foo”, and then creating a variable in a method named “foo”, the method’s foo is different from the field.

Edit: To make this completely clear, here’s an example that won’t compile:

``````public class Example<T>  {

public T t;

public T Get<T>() {
return t;
}
}
``````

the T t isn’t a valid return value, because Get introduces it’s own T type variable, which shadows (technical term!) the T of Example. If you just define Get as “public T Get() { return t; }”, that’ll work, as now we’re talking about the same T as the Example’s T.

So the type constraints from your code (where T : NodeBase) had nothing to do with the compilation error.

Note:
T is not a magical symbol, it’s just used a lot to stand in for __t__ype in a generic definition, the same way “i” is used for the __i__terator in a for-loop. In your case, I would define the class as GridBase where NodeType : NodeBase, so it’s easier to see from the method what’s going on.

Thanks that worked, one more question. How can I apply addition constraint on nodeBase for that function withou redefining eg.I want a constraint INodeAttrGridable

``````    public T GetNodeFromWorldPoint(Vector3 worldPositionIn )where T : INodeAttrGridable
{
//
// Convet the worldPosition into a percentage
float percentX = (worldPositionIn.x + gridWorldSize.x/2) / gridWorldSize.x;
float percentY = (worldPositionIn.z + gridWorldSize.y/2) / gridWorldSize.y;
percentX = Mathf.Clamp01(percentX);
percentY = Mathf.Clamp01(percentY);

//
// Convert percentage into index
int x = Mathf.RoundToInt((gridSizeX-1) * percentX);
int y = Mathf.RoundToInt((gridSizeY-1) * percentY);

return grid[x,y];
}
``````

You can’t because you’re not guaranteeing that NodeBase (the constraint on the class and therefore on grid) is also INodeAttrGridable. If you want to return that interface then make it return it explicitly (which is the better choice here since that seems to be what you mean. If all you care about is the interface contract then return the interface and only interact with it in that manner).

Thanks everyone for the help got this working nicely

One last question relating to this. Is it possible to overwrite my public T[,] CreateGrid(T node) given that the class is generic and constraint to a node type eg

``````using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/*
* This is the base class for creating a grid containing
* a give node derived from nodeBase class
*/

public class GridBase<T> : MonoBehaviour where T : NodeBase {

public T node;
public T[,] grid;
[HideInInspector]
public int gridSizeX, gridSizeY;        // This this the number of the grid to generate nodes in
public bool displayGridGizmos;            // Toggle GizmoDraw
public Vector2 gridWorldSize;            // This the world size in WS, grid will fit itself in here depending on the nodeRadius
public float nodeRadius;                // Node radius we use to generate our grid sizes
public float nodeDiameter;                // Node diameter we use to generate our grid sizes

//--------------------------------------------------------------------
// GridBase base functions
//--------------------------------------------------------------------

//
// Create Grid from any node inherated from NodeBase
public T[,] CreateGrid(T node) {

//
// Set Grid size based on node Diameter
gridSizeX = Mathf.RoundToInt(gridWorldSize.x/nodeDiameter);
gridSizeY = Mathf.RoundToInt(gridWorldSize.y/nodeDiameter);

//
// Create Grid with given size
grid = new T[gridSizeX, gridSizeY];

//
// Find worldBottomLeft
Vector3 worldBottomLeft = transform.position - Vector3.right * gridWorldSize.x / 2 - Vector3.forward * gridWorldSize.y / 2;

//
// Populate grid
for (int x = 0; x < gridSizeX; x++) {
for (int y = 0; y < gridSizeY; y++) {
Vector3 worldPoint = worldBottomLeft + Vector3.right * (x * nodeDiameter + nodeRadius) + Vector3.forward * (y * nodeDiameter + nodeRadius);
grid [x, y] = System.Activator.CreateInstance(typeof(T), worldPoint, x, y) as T; /*This comes at a performace cost */
}
}

//
// Return Grid
return grid;
}

}
``````

Every node inherits from nodeBase and every grid inherits from gridBase

``````using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GridAStar : GridBase<NodeAStar>, IGridAStarable{

//
// TEST
public  override T[,] CreateGrid<T>(T node) {

return grid;
}

}
``````

GridAStar.CreateGrid(T)’ is marked as an override but no suitable method found to override

Gotta mark methods you want to override in C# with virtual. So do that first:

``````// in GridBase:
public virtual T[,] CreateGrid(T node) {
... //as before
}
``````

Secondly, in GridAStart you’ve already bound T to NodeAStar, so the method would be:

``````public override NodeAStar[,] CreateGrid(NodeAStar nodeAStar)
{
return grid;
}
``````