我的情况是我有一个 Bag
,里面有一个 AddSlot
方法。
我有两种包,ItemsBag
和 DCBag
(代表可拖动内容)
ItemsBag
是一个二维包,意味着它有行和列,DCBag
是一维的,它只有一列但有很多行(这意味着我也可以认为它是二维的)。
现在的问题是,由于第一个包处理二维索引,我希望 AddSlot
签名是这样的:
public void AddSlot(int r, int c);
另一个包的AddSlot
:
public void AddSlot(int r);
我如何在 AddSlot
中编写 Bag
的虚拟/抽象签名,以便当 ItemsBag
和 DCBag
从 Bag
继承时,它们可以按照我上面提到的方式覆盖签名?
正如我所说,我可以认为 DCBag
也是二维的,因此它和 ItemsBag
具有相同的签名,但我真的很想知道我是否可以这样做,这很有趣。
我可以使用可变数量的参数 params obejct[] args
来摆脱困境,但最好以不涉及装箱/拆箱的方式进行。
我也可以制作一个 TwoDimBag
和 OneDimBag
让它们都继承自 Bag
,按照我想要的方式在其中写入 AddSlot
的定义,然后让 ItemsBag
继承 TwoDimBag
和DCBag
继承 OneDimBag
,但我不是在寻找解决方法,而是在寻找如何实现我所要求的东西。
再次回顾一下最后一次:我如何写一个我可以在继承的 child 中覆盖的签名? (也就是说,如果我可以并且有办法的话)
谢谢。
编辑:(额外信息)
Bag
有很多功能。这两个袋子之间的区别在于 ItemsBag
拥有一个二维的插槽列表( List<List<Slot>>
),而 DCBag
拥有一个一维的 List
的 Slot
。它是持有 Slot
的 Item
。 - ItemsBag
中的项目可以占用多个 Slot
,DCBag
中的项目只能占用一个。
一些你可以在两个包中做的事情: AddSlot
, FreeSlot
, AddItem
(添加策略不同,在 ItemsBag
中还有额外的添加方法),在两个包中你可以取一个用鼠标元素,交换元素,分类元素,两个包也会收到来自插槽的通知,以采取必要的行动,如Notify_ClickedOnEmptySlot(Slot slot)
一些你只能在 ItemsBag
中做的事情:
组合项目、添加一行插槽、添加一列插槽和旋转项目。
以下是这些包在外观上的不同之处,ItemsBag
(here's 一个旧演示):
DCBag
:
最佳答案
如果对象是元素袋,则考虑使元素类型为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/