c# - 我可以编写一个可以在继承的子项中覆盖的通用方法签名吗?

标签 c# inheritance overriding signature

我的情况是我有一个 Bag,里面有一个 AddSlot 方法。 我有两种包,ItemsBagDCBag(代表可拖动内容) ItemsBag 是一个二维包,意味着它有行和列,DCBag 是一维的,它只有一列但有很多行(这意味着我也可以认为它是二维的)。

现在的问题是,由于第一个包处理二维索引,我希望 AddSlot 签名是这样的:

public void AddSlot(int r, int c);

另一个包的AddSlot:

public void AddSlot(int r);

我如何在 AddSlot 中编写 Bag 的虚拟/抽象签名,以便当 ItemsBagDCBagBag 继承时,它们可以按照我上面提到的方式覆盖签名?

正如我所说,我可以认为 DCBag 也是二维的,因此它和 ItemsBag 具有相同的签名,但我真的很想知道我是否可以这样做,这很有趣。

我可以使用可变数量的参数 params obejct[] args 来摆脱困境,但最好以不涉及装箱/拆箱的方式进行。

我也可以制作一个 TwoDimBagOneDimBag 让它们都继承自 Bag ,按照我想要的方式在其中写入 AddSlot 的定义,然后让 ItemsBag 继承 TwoDimBagDCBag 继承 OneDimBag ,但我不是在寻找解决方法,而是在寻找如何实现我所要求的东西。

再次回顾一下最后一次:我如何写一个我可以在继承的 child 中覆盖的签名? (也就是说,如果我可以并且有办法的话)

谢谢。

编辑:(额外信息) Bag 有很多功能。这两个袋子之间的区别在于 ItemsBag 拥有一个二维的插槽列表( List<List<Slot>> ),而 DCBag 拥有一个一维的 ListSlot 。它是持有 SlotItem 。 - ItemsBag 中的项目可以占用多个 SlotDCBag 中的项目只能占用一个。

一些你可以在两个包中做的事情: AddSlot , FreeSlot , AddItem (添加策略不同,在 ItemsBag 中还有额外的添加方法),在两个包中你可以取一个用鼠标元素,交换元素,分类元素,两个包也会收到来自插槽的通知,以采取必要的行动,如Notify_ClickedOnEmptySlot(Slot slot)

一些你只能在 ItemsBag 中做的事情: 组合项目、添加一行插槽、添加一列插槽和旋转项目。

以下是这些包在外观上的不同之处,ItemsBag(here's 一个旧演示):

enter image description here

DCBag :

enter image description here

最佳答案

如果对象是元素袋,则考虑使元素类型为generic .

即你会有一个通用的 Bag<T>类:

class Bag<T>
{
     private readonly List<T> _items = new List<T>();
     public void AddSlot(T item)
     {
         _items.Add(item);
     }
}

在这种情况下,您的项目类型可以是任何类型:

class Item1D
{ 
    public int Value { get; set; }
}

class Item2D
{
    public int X { get; set; }
    public int Y { get; set; }
}

假设所有元素的“包”功能都相同,您将通过传递适当的通用类型来实例化不同的包:

var bag1D = new Bag<Item1D>();
var bag2D = new Bag<Item2D>();

或者,您甚至可以将项目列表作为通用参数传递:

var bagOfSlots = new Bag<Slot>();
var bagOfListOfSlots = new Bag<List<Slot>>();

查看 System.Collections.Generic 中的类(class)命名空间,这是一般的想法。此外,您是否真的需要将其虚拟化取决于 Bag 的职责。类应该是(查看 Single responsibility principle )。 OOP 中的一条经验法则是使类的职责尽可能简单(“包”仅表示项目的无序集合)。

[更新]

如果DCBag或多或少是一个 ItemBag使用单列,则可以使用 new更改方法签名的关键字,同时仍然可以访问基本方法:

class ItemBag
{
    public virtual void AddSlot(int r, int c)
    {

    }
}

class DCBag : ItemBag
{
    public new void AddSlot(int r)
    {
        // we only have a single column
        base.AddSlot(r, 0);
    }
}

请注意,这不是覆盖该方法,而是创建一个具有相同名称的新方法。换句话说,您可以调用:

ItemBag itemBag = new ItemBag();
itemBag.AddSlot(3, 4);

DCBag dcBag = new DCBag();
dcBag.AddSlot(3);

但是你不能有动态调度(我想在这种情况下你不需要它):

// if dcBag is of type ItemBag
ItemBag dcBag;

// ...and you instantiate it to a DCBag...
dcBag = new DCBag();

// ...you still end up with a virtual signature...
dcBag.AddSlot(3, 4);

// ...and the new method is inaccessible
dcBag.AddSlot(3); // <-- this will not compile

关于c# - 我可以编写一个可以在继承的子项中覆盖的通用方法签名吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18482296/

相关文章:

javascript - 如何覆盖javascript native 对象的内置方法

java - 策略模式中的通用方法重写

c# - 将控制台输出重定向到 winforms ListBox

c# - 带有运算符的泛型 C#

c++ - 多个基类可以有相同的虚方法吗?

python - 覆盖 Python 类 __str__ 方法的最佳方法是什么?

c# - 使用使用 int 参数调用的 Action 初始化任务

c# - .NET TabControl/TabPage 中的选项卡很丑

java - java中继承的问题

c# - virtual、override、new和sealed override的区别