我对C#很陌生,我相信类似的问题已经得到了回答,但我不确定要搜索什么,所以问题就在这里:
我有两个类,它们有一些相同的方法和构造函数。但是,这些方法和构造函数接受不同类型的参数(Dictionaries变量是不同的)。那么如何将这些方法和构造函数放入抽象类Brain
?
Brain.cs
public abstract class Brain
{
protected int width;
protected int height;
}
Reward.cs
public class Reward:Brain
{
public Dictionary<Tuple<Point, Direction>, int> r =
new Dictionary<Tuple<Point, Direction>, int>();
public Reward(int w, int h)
{
int directionsCount = Enum.GetNames(typeof(Direction)).Length;
int direction;
width = w;
height = h;
for (int i = 0; i < w; i++)
for (int j = 0; j < h; j++)
for (direction = 0; direction < directionsCount; direction++)
{
Point state = new Point(i, j);
r[Tuple.Create(state, (Direction)direction)] = 0;
}
}
public void Set(Point state, Direction direction, int reward)
{
r[Tuple.Create(state, direction)] = reward;
}
public int Get(Point state, Direction direction)
{
return r[Tuple.Create(state, direction)];
}
}
Quantity.cs
public class Quantity:Brain
{
public Quantity(int w, int h)
{
.........
for (int i = 0; i < width; i++)
for (int j = 0; j < height; j++)
for (direction = 0; direction < directionsCount; direction++)
{
Point state = new Point(i, j);
Set(state, (Direction)direction, 0);
}
}
private Dictionary<Tuple<Point, Direction>, decimal> q =
new Dictionary<Tuple<Point, Direction>, decimal>();
.....
public decimal Get(Point state, Direction action)
{
return q[Tuple.Create(state, action)];
}
public void Set(Point state, Direction action, decimal value)
{
q[Tuple.Create(state, action)] = value;
}
}
答案 0 :(得分:2)
将Brain定义为通用类(https://msdn.microsoft.com/library/sz6zd40f.aspx):
public abstract class Brain<T>
{
protected int width;
protected int height;
public Dictionary<Tuple<Point, Direction>, T> r =
new Dictionary<Tuple<Point, Direction>, T>();
public void Set(Point state, Direction direction, T reward)
{
r[Tuple.Create(state, direction)] = reward;
}
public T Get(Point state, Direction direction)
{
return r[Tuple.Create(state, direction)];
}
}
而且你可以将你的课程定义为:
public class Reward : Brain<int>
{
}
public class Quantity : Brain<decimal>
{
}
您或许可以将Reward
和Quantity
方法重新定义为基类中的一种方法,它们看起来非常可能,但我不知道,您隐藏的代码中发生了什么背后&#34; ...&#34;
答案 1 :(得分:0)
你可以使用泛型来做到这一点:
"zone.js": "0.7.2"
并声明派生类如下:
npm install
但是这样做的缺点是public abstract class Brain<TValue> // TValue is the generic type parameter
{
protected int width;
protected int height;
// use TValue in the declarations
public Dictionary<Tuple<Point, Direction>, TValue> r = new Dictionary<Tuple<Point, Direction>, TValue>();
public abstract void Set(Point state, Direction direction, TValue reward);
public abstract TValue Get(Point state, Direction direction);
}
和public class Reward : Brain<int> // int is now the generic type argument
{
public override void Set(Point state, Direction direction, int reward)
{
r[Tuple.Create(state, direction)] = reward;
}
public int Get(Point state, Direction direction)
{
return r[Tuple.Create(state, direction)];
}
}
public class Quantity : Brain<decimal>
{ ... }
是完全不同的不变类型。因此,您无法将Brain<int>
的实例和Brain<decimal>
的实例分配给Reward
类型的同一变量:
Quantitiy
因此,如果您只想继承功能或声明,那么通用方法就可以了。但是,如果您希望将Brain<sometype>
和Brain<int> brain = new Reward(0, 0); // works
brain = new Quantitiy(0,0); // fails because Quantity is not a Brain<int>
个实例放在Reward
中,则无法使用。
答案 2 :(得分:0)
好吧,我会考虑你的设计的替代品。
继承不应用于代码重用目的,而应用于Is-A关系。最好使用组合:Inheritance (IS-A) vs. Composition (HAS-A) Relationship。
public class Brain<T>
{
private readonly int width;
private readonly int height;
private readonly Dictionary<Tuple<Point, Direction>, T> r;
Brain(int width, int height)
{
this.width = width;
this.height = height;
.........
r = new Dictionary<Tuple<Point, Direction>, T>();
for (int i = 0; i < width; i++)
for (int j = 0; j < height; j++)
foreach (Direction direction in Enum.GetValues(typeof(Direction))
{
var state = new Point(i, j);
Set(state, direction, default(T));
}
}
public void Set(Point state, Direction direction, T reward)
{
r[Tuple.Create(state, direction)] = reward;
}
public T Get(Point state, Direction direction)
{
return r[Tuple.Create(state, direction)];
}
}
然后其他类将使用组合。例如,对于Reward
类:
public class Reward
{
Reward(int width, int height)
{
rewards = new Brain<int>(width, height);
// Somehow initialize actual rewards here...
rewards.Set(new Point(5, 8), Direction.Up, 10); // fictif example
}
private readonly Brain<int> rewards;
}
因此Brain
类基本上管理每个职位的信息。
然后,我可能会考虑是否真的值得拥有多种类型。也许之后的奖励也可能是decimal
,特别是如果它们在某个时间点乘以已经decimal
的数量。
然而,更好的方法是建立一个代表给定位置和方向的所有信息的类:
public class PositionInfo
{
public PositionInfo(int reward, decimal quantity)
{
Reward = reward;
Quantity = quantity.
}
public int Reward { get; } // C# 6 - Read-only properties.
public decimal Quantity { get; }
}
如果许多项目使用默认值且维度很大,您可以考虑使用TryGetValue
并仅填充未使用默认值的位置/方向信息。然后修改Get
以在项目不在字典中时返回默认信息。事实上,如果所有位置都被填充,那么使用多维数组可能是更好的选择。
我还会添加System.Diagnostics.Debug.Assert
之类的验证来帮助在开发过程中发现错误。