本文底部是一个解决方案的示例,尽管该示例显然是无效的,因为它在继承时使用了 BaseNode 和 BaseEdge 而没有提供类型。
我正在尝试创建一个抽象图类,其中节点类和边类也必须是抽象的。每个类的单独实现将添加方法和属性以及实现基类的抽象方法。
我有一个现有的解决方案,仅使用基本类型来处理所有内容,但是我很快发现自己陷入了混乱的铸造中。
只有图类必须公开,尽管其他类可以,因此涉及嵌套在图类中的节点和边类的解决方案是可以接受的。
有没有什么方法可以构建这样的结构,使得所有属性都属于正确的类型,而无需在系统中的任何地方进行昂贵的转换?更重要的是,实现类不必到处进行强制转换,但在这种情况下性能绝对是一个问题(实际上是这样),所以我宁愿完全避免强制转换。
abstract class Graph<TNode, TEdge>
where TNode : BaseNode<TEdge>
where TEdge : BaseEdge<TNode>
{
TNode root;
List<TNode> nodes;
List<TEdge> edges;
public abstract float process();
}
abstract class BaseNode<TEdge>
// THIS HERE IS THE PROBLEM
where TEdge : BaseEdge
{
List<TEdge> inputs;
public List<TEdge> Inputs
{
get
{
return inputs;
}
}
public abstract float process();
}
abstract class BaseEdge<TNode>
// THIS HERE IS THE PROBLEM
where TNode : BaseNode
{
TNode from;
TNode to;
public TNode To
{
get
{
return to;
}
}
public TNode From
{
get
{
return from;
}
}
public abstract float process();
}
@Marceln 想看看我现有的实现,所以就在这里。没有泛型的话,这只是同样的事情。
abstract class Graph
{
BaseNode root;
List<BaseNode> nodes;
List<BaseEdge> edges;
public abstract float process();
}
abstract class BaseNode
{
List<BaseEdge> inputs;
public List<BaseEdge> Inputs
{
get
{
return inputs;
}
}
public abstract float process();
}
abstract class BaseEdge
{
BaseNode from;
BaseNode to;
public BaseNode To
{
get
{
return to;
}
}
public BaseNode From
{
get
{
return from;
}
}
public abstract float process();
}
Node 的实现可能如下所示:
class ImplementedNode : BaseNode
{
public override float process()
{
foreach (ImplementedEdge edge in this.Inputs)
{
// Something
}
}
public bool getImplementationSpecificInfo()
{
return true;
}
}
如果您愿意放松对
BaseEdge
和 BaseNode
的限制,那么您可以执行如下示例所示的操作。
我引入了接口
INode
和 IEdge
,因此任何使用此接口的人都不允许创建任何类型的 BaseEdge
和 BaseNode
的具体子类。
public interface INode
{
}
public interface IEdge
{
}
public abstract class Graph<TNode, TEdge>
where TNode : BaseNode<TEdge>
where TEdge : BaseEdge<TNode>
{
public TNode Root { get; set; }
public List<TNode> Nodes { get; set; }
public List<TEdge> Edges { get; set; }
}
public abstract class BaseNode<TEdge> : INode where TEdge: IEdge
{
List<TEdge> inputs;
public List<TEdge> Inputs
{
get
{
return inputs;
}
}
public abstract float process();
}
public abstract class BaseEdge<TNode> : IEdge where TNode: INode
{
TNode from;
TNode to;
public TNode To
{
get
{
return to;
}
}
public TNode From
{
get
{
return from;
}
}
public abstract float process();
}
public class ConcreteNode : BaseNode<ConcreteEdge>
{
public override float process()
{
return 0;
}
}
public class ConcreteEdge : BaseEdge<ConcreteNode>
{
public override float process()
{
return 0;
}
}
public class ConcreteGraph : Graph<ConcreteNode, ConcreteEdge>
{
}
更新
另一个答案,它提供了某种类型安全性。
public interface IGraph<TNode, TEdge>
where TNode : INode
where TEdge : IEdge
{
TNode Root { get; set }
List<TNode> Nodes { get; set; }
List<TEdge> Edges { get; set; }
}
public interface INode
{
List<IEdge> Edges { get; set; }
}
public interface INode<TEdge> where TEdge : IEdge
{
List<TEdge> Edges { get; set; }
}
public interface IEdge
{
INode To { get; set; }
INode From { get; set; }
}
public interface IEdge<TNode> where TNode : INode
{
TNode To { get; set; }
TNode From { get; set; }
}
public class MyGraph : IGraph<MyNode, MyEdge>
{
public MyGraph(MyNode root)
{
Root = root;
}
public MyNode Root { get; set; }
public List<MyNode> Nodes { get; set; }
public List<MyEdge> Edges { get; set; }
}
public class MyNode : INode<MyEdge>, INode
{
public List<MyEdge> Edges { get; set; }
List<IEdge> INode.Edges
{
get { return this.Edges; }
set { this.Edges = value; }
}
}
public class MyEdge : IEdge<MyNode>, IEdge
{
public MyNode To { get; set; }
public MyNode From { get; set; }
INode IEdge.To
{
get { return this.To; }
set { this.To = value; }
}
INode IEdge.From
{
get { return this.From; }
set { this.From = value; }
}
}
这没有给我带来编译错误。
更新
这个答案不起作用。但是,我将其留在这里以供与它一起出现的评论。
@NodeDear,我认为当
Graph
是通用的时,你原来的示例是正确的:
Graph<TNode, TEdge> where TNode : BaseNode<TEdge>, TEdge : BaseEdge<TNode>
在您为@marceln 提供的示例中,
Graph
类不是通用的。因此,你必须进行各种铸造。但使用通用版本:
public abstract Graph<TNode, TEdge>
where TNode : BaseNode<TEdge>
where TEdge : BaseEdge<TNode>
{
public TNode Root { get; set; }
public List<TNode> Nodes { get; set; }
public List<TEdge> Edges { get; set; }
}
public abstract BaseNode<TEdge> where TEdge : BaseEdge<BaseNode<TEdge>>
{
public List<TEdge> Edges { get; set; }
}
public abstract BaseEdge<TNode> where TNode : BaseNode<BaseEdge<TNode>>
{
public TNode To { get; set; }
public TNode From { get; set; }
}
public class MyNode : BaseNode<TEdge> where TEdge : BaseEdge<MyNode>
{
...
}
public class MyEdge : BaseEdge<TNode> where TNode : BaseNode<MyEdge>
{
...
}
public class MyGraph : Graph<MyNode, MyEdge>
{
...
}
public MyGraph<MyNode, MyEdge> g = new MyGraph<MyNode, MyEdge>();
List<MyEdge> edges = g.Nodes[0].Edges;
MyNode toNode = g.Edges[0].To;
这允许从
Graph<TNode, TEdge>
派生的任何类型都具有强类型节点和边,这正是OP正在寻找的。
我找到了解决办法
public interface IGraph<TNode, TEdge>
where TNode : INode<TNode, TEdge>
where TEdge : IEdge<TNode, TEdge>
{
public IEnumerable<TNode> Nodes { get; }
public IEnumerable<TEdge> Edges { get; }
}
public interface INode<TNode, TEdge> where TEdge : IEdge<TNode, TEdge> where TNode : INode<TNode, TEdge>
{
IEnumerable<TEdge> Edges { get; }
IEnumerable<TNode> Neighbors { get; }
}
public interface IEdge<TNode, TEdge> where TEdge : IEdge<TNode, TEdge> where TNode : INode<TNode, TEdge>
{
TNode To { get; }
TNode From { get; }
}
public class Graph : IGraph<Node, Edge>
{
public IEnumerable<Node> Nodes { get; }
public IEnumerable<Edge> Edges { get; }
}
public class Node : INode<Node, Edge>
{
public IEnumerable<Edge> Edges { get; }
public IEnumerable<Node> Neighbors { get; }
}
public class Edge : IEdge<Node, Edge>
{
public Node To { get; }
public Node From { get; }
}