首页 > 解决方案 > 如何添加具有不同签名但已知类型的方法符合接口?

问题描述

考虑以下代码:

public interface IStackable {
    Item Item;
    int Amount;
}

// I have an Item data
public class Item {
    private string _name;
    private string _description;
}

// composite pattern: adding amount to item data
public class StackableItem : IStackable {
    private Item _item;
    private int _amount;

    public Item Item => _item;
    public int Amount => _amount;

    public void AddAmount(int amount) {
        this._amount += amount; 
    }

    // *How to make this conform to interface?
    // public void AddItem(StackableItem item) {}

    public void AddItem(IStackable stackable) {
        this._amount += stackable.GetAmount();
    } 
}

// composite pattern: adding amount to item data
public class UniqueItem : IStackable {
    private List<Item> _items;

    public Item Item => _items.First();
    public int Amount => _items.Count;

    public void AddItem(Item item) {
        _items.Add(item);
    }

    // *How to make this conform to interface?
    // public void AddItem(UniqueItem item) {}

    public void AddItem(IStackable stackable) {
        _items.Add() // how am I supposed to resolve this?

        // pseudo code:
        // for every item in stackable (but it has to be uniqueitem),
        // add every item from stackable to this object;
        // then I need to destroy that stackable object
    } 

}

我认为将 AddItem(IStackable stackable) 添加到界面会很糟糕。即使我这样做了,我也无法制作出按预期工作的方法。

我能想到的唯一方法是先将 Stackable 转换为 Unique Items,但我相信这也不是一个好方法。

*我认为最好的方法是添加具有不同签名的方法符合接口,那么如何添加具有不同签名但已知类型的方法符合接口?

编辑:

StackableItem 示例:药水 x10

UniqueItem 示例:3 把枪,每把枪都有不同的弹药

IStackable 用于 UI,因此 UI 不需要知道它们的实现,仍然可以相应地显示 Item 和 Amount,(并且无论实现如何都整齐地成为一个 Item slot)

标签: c#oopunity3ddesign-patterns

解决方案


是的,你可以简单地做

public interface IStackable 
{
    Item GetItem();
    int GetAmount();

    void AddItem(int amount);
    void AddItem(IStackable item);
}

我猜你想问的是:你要确保只有StackableItemStackableItem.

我基本上看到两种选择:

  • 通过强制转换进行运行时检查。要么使用is

    public void AddItem(IStackable stackable) 
    {
        if(stackable == null)
        {
            Debug.LogError("Null passed!");
            return;
        }
    
        if(stackable is StackableItem item)
        {
            this._amount += item.GetAmount();
        }
        else
        {
            Debug.LogError($"Unexpected type {stackable.GetType} passed but expected {typeof(StackableItem)}");
        }
    } 
    

    或者as

    public void AddItem(IStackable stackable) 
    {
        if(stackable == null)
        {
            Debug.LogError("Null passed!");
            return;
        }
    
        var item = stackable as StackableItem;
        if(item != null)
        {
            this._amount += item.GetAmount();
        }
        else
        {
            Debug.LogError($"Unexpected type passed! Expected {typeof(StackableItem)}");
        }
    } 
    
  • 使用通用接口

    public interface IStackable 
    {
        Item GetItem();
        int GetAmount();
        void AddItem(int amount);
    }
    
    public interface IStackable<T> : IStackable where T : IStackable
    {
        void AddItem(T item);
    }
    

    让你的班级继承

    public class StackableItem : IStackable<StackableItem>
    {
        ...
    
        public void AddItem(StackableItem stackable)
        {
            _amount += stackable.GetAmount();
        }
    
        public void AddItem (int amount)
        {
            _amount += amount;
        }
    }
    

推荐阅读