分层收集的通用接口

发布于 2024-10-29 16:32:41 字数 777 浏览 1 评论 0原文

我想创建一个严格遵循以下结构的层次结构:

(1) INodeBase - 包含一个 Children 属性,该属性是其自身的集合 (INodeBase)

(2) INodeFolder - 派生自 INodeBase。

(3) NodeFolder - 实现 INodeFolder。 Children 属性的实现应该允许它包含 INodeFolder 类型和 INodeItem 类型的项目。

(4) INodeItem - 派生自 INodeBase。

(5) NodeItem - 实现 INodeItem。 Children 属性的实现应该允许它包含 NodeResult 类型的项目。

(6) INodeResult - 派生自 INodeBase。

(7) NodeResult - 实现 INodeResult - 我不需要/想要此类中的子属性,但是,如果可以正确构建整体层次结构,我愿意在类中挂起一个空集合。

本质上,我想要节点的一种基本类型 - 并且假设应该是一个节点可以包含其他节点。我认为泛型是可行的方法 - 但是 - 问题是,如果我查询整个分层集合,或者更确切地说,如果我对其进行过滤,当我递归地遍历每个孩子的子集合(即展平我的集合),我想知道什么是什么 - 即,如果我在文件夹的 Children 集合中,我想知道何时点击FolderNode,何时点击 ItemNode,然后何时递归遍历文件夹的 Children 属性一个 ItemNode,我想知道我只是在处理 NodeResult 类型。

那么,针对上述情况的最佳方法是什么?

克里斯

I want to create a hierarchical structure that will closely follow the following structure:

(1) INodeBase - contains a Children property that is a Collection of itself (INodeBase)

(2) INodeFolder - derives from INodeBase.

(3) NodeFolder - implements INodeFolder. The implementation of the Children property should allow it to contain items of both the INodeFolder type and INodeItem type.

(4) INodeItem - derives from INodeBase.

(5) NodeItem - implements INodeItem. The implementation of the Children property should allow it to contain items of the NodeResult type.

(6) INodeResult - derives from INodeBase.

(7) NodeResult - implements INodeResult - I don't need/want a children property in this class, but, I am willing to have an empty collection hang off of the class if the overall hierarchy can be structured properly.

Essentially, I want one base type for node - and the assumption should be that a node can contain other nodes. I am thinking that generics is the way to go - but - the problem is that if I query off of the overall hierarchical collection, or rather, if I filter on it, when I am recursively going through each child's children collection (i.e. flattening my collection), I want to know what is what - i.e., if I am in the Children collection of a folder, I want to know when I hit a FolderNode and when I hit an ItemNode, and then when I recurse through the Children property of an ItemNode, I want to know that I am just dealing with the NodeResult type.

So, what is the best approach for the above?

Chris

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

话少情深 2024-11-05 16:32:41

我认为下面的代码都遵循您想要的规则,特别是所有实现 INodeBase 的节点,以及 NodeResult 没有 Children 的好处> 收藏。

以下是所需的接口:

public interface INodeBase
{
}

public interface INodeContainer : INodeBase
{
}

public interface INodeContainer<C> : INodeContainer
    where C : INodeBase
{
    IList<C> Children { get; }
}

public interface INodeFolder : INodeContainer<INodeContainer>
{
}

public interface INodeItem : INodeContainer<INodeResult>
{
}

public interface INodeResult : INodeBase
{
}

我添加了几个 INodeContainer 接口 - 一个是非通用的,另一个是 INodeContainer。另一个通用的。

以下是类定义:

public abstract class NodeBase : INodeBase
{
}

public abstract class NodeBase : INodeBase
{
}

public abstract class NodeContainer : NodeBase, INodeContainer
{
}

public abstract class NodeContainer<C> : NodeContainer, INodeContainer<C>
    where C : INodeBase
{
    public NodeContainer() { this.Children = new List<C>(); }
    public IList<C> Children { get; private set; }
}

public class NodeFolder : NodeContainer<INodeContainer>, INodeFolder
{
}

public class NodeItem : NodeContainer<INodeResult>, INodeItem
{
}

public class NodeResult : INodeResult
{
}

现在您可以使用如下代码:

var nf = new NodeFolder();
nf.Children.Add(new NodeFolder()); // Add `INodeFolder`
var ni = new NodeItem();
nf.Children.Add(ni);  // or add `INodeFolder`, but nothing else.
var nr = new NodeResult();
ni.Children.Add(nr); // Only add `INodeResult`.
// nr does not have "Children" collection.

如果您愿意,您可以将 INodeContainer 限制在具体类型而不是接口上。这取决于您是想通过接口还是通过具体类来引用对象。

让我知道这是否适合您。

I think the below code all follows the rules you wanted, particularly with all node implementing INodeBase and with the bonus that NodeResult doesn't have a Children collection.

Here are the interfaces required:

public interface INodeBase
{
}

public interface INodeContainer : INodeBase
{
}

public interface INodeContainer<C> : INodeContainer
    where C : INodeBase
{
    IList<C> Children { get; }
}

public interface INodeFolder : INodeContainer<INodeContainer>
{
}

public interface INodeItem : INodeContainer<INodeResult>
{
}

public interface INodeResult : INodeBase
{
}

I have added a couple of INodeContainer interfaces - one non-generic & the other generic.

Here are the class definitions:

public abstract class NodeBase : INodeBase
{
}

public abstract class NodeBase : INodeBase
{
}

public abstract class NodeContainer : NodeBase, INodeContainer
{
}

public abstract class NodeContainer<C> : NodeContainer, INodeContainer<C>
    where C : INodeBase
{
    public NodeContainer() { this.Children = new List<C>(); }
    public IList<C> Children { get; private set; }
}

public class NodeFolder : NodeContainer<INodeContainer>, INodeFolder
{
}

public class NodeItem : NodeContainer<INodeResult>, INodeItem
{
}

public class NodeResult : INodeResult
{
}

Now you can use the code like this:

var nf = new NodeFolder();
nf.Children.Add(new NodeFolder()); // Add `INodeFolder`
var ni = new NodeItem();
nf.Children.Add(ni);  // or add `INodeFolder`, but nothing else.
var nr = new NodeResult();
ni.Children.Add(nr); // Only add `INodeResult`.
// nr does not have "Children" collection.

You can restrict INodeContainer<C> on the concrete types rather than the interfaces if you wish. It depends on if you want to reference the objects by interface or by concrete class.

Let me know if this works for you.

稳稳的幸福 2024-11-05 16:32:41

不过,这不是主要答案,为什么不直接使用类和对象而不是接口来设计对象层次结构。稍后您可以将其转变为界面层次结构。

enum NodeTypes { Unknown, Folder, File };

public abstract class CNodeBase {

    protected List<CNodeBase> FItems;

    public List<CNodeBase> Items();

    public virtual NodeTypes NodeType() {
        return NodeTypes.Unknown;
    }
}

public class CNodeFolder: CNodeBase {

// ...

    public override NodeTypes NodeType() {
        return NodeTypes.Folder;
    }

}

public class CNodeFile: CNodeBase {

// ...

    public override NodeTypes NodeType() {
        return NodeTypes.File;
    }

}

public class CDemo {

    void main () {
        // root node is ALWAYS A folder
        CNodeFolder RootNode = new CNodeFolder("\\");

        CNodeBase AnyNode = null;

        AnyNode = new CNodeFolder("c:");
        RootNode.Add(AnyNode);

        AnyNode = new CNodeFolder("d:");
        RootNode.Add(AnyNode);

        AnyNode = new CNodeFile("readme.txt");
        RootNode.Add(AnyNode);  
    }
}

超类(抽象的或具体的)的工作方式与接口非常相似,但具有的优点是您可以从中实例化对象,请参阅代码的工作原理。

在我看来,你正在尝试做一些非常概念化的事情。也许如果你退一步,去学习可以实例化的类,你可能会对你的想法有一个更实际的看法。

界面是一个非常好的功能,但一开始很难理解。有时候,“退一步,进五步”也是个好主意。

Altought, is not the main answer, why don't you design your object hierarchy, directly with classes and objects, instead of interfaces. Later you may turn it into an interface hierarchy.

enum NodeTypes { Unknown, Folder, File };

public abstract class CNodeBase {

    protected List<CNodeBase> FItems;

    public List<CNodeBase> Items();

    public virtual NodeTypes NodeType() {
        return NodeTypes.Unknown;
    }
}

public class CNodeFolder: CNodeBase {

// ...

    public override NodeTypes NodeType() {
        return NodeTypes.Folder;
    }

}

public class CNodeFile: CNodeBase {

// ...

    public override NodeTypes NodeType() {
        return NodeTypes.File;
    }

}

public class CDemo {

    void main () {
        // root node is ALWAYS A folder
        CNodeFolder RootNode = new CNodeFolder("\\");

        CNodeBase AnyNode = null;

        AnyNode = new CNodeFolder("c:");
        RootNode.Add(AnyNode);

        AnyNode = new CNodeFolder("d:");
        RootNode.Add(AnyNode);

        AnyNode = new CNodeFile("readme.txt");
        RootNode.Add(AnyNode);  
    }
}

Superclasses (both abstract or concrete) work very similar to interfaces, but have the advantage that you can instantiate objects from them, see the code working.

Its seems to me, that you are trying to do something very conceptual. Maybe if you step back a little, going to classes that can be instantiated, you may get a more practical view of your idea.

Interfaces are a very good feature, yet, its difficult to understand, at first. Sometimes, is a good idea to "take one step back, to go five steps forward".

故事和酒 2024-11-05 16:32:41

为什么需要让文件夹和项目实现相同的接口?

在我看来,像这样的更简单的结构会更好......

public class Folder
{
    public List<Folder> Folders { get; }
    public List<Item> Items { get; }
}

public class Item
{
    public List<Result> Results { get; }
}

public class Result
{

}

Why do you need to have folders and items implement the same interface?

It seems to me that a simpler structure like this would work better...

public class Folder
{
    public List<Folder> Folders { get; }
    public List<Item> Items { get; }
}

public class Item
{
    public List<Result> Results { get; }
}

public class Result
{

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文