Как добавить метод с другой сигнатурой, но с известным типом, соответствующим интерфейсу? - PullRequest
0 голосов
/ 13 февраля 2020

Рассмотрим следующий код:

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 to Unique Items, но я считаю, что это не очень хороший способ.

* Я думаю, что лучший способ - это добавить метод с другой сигнатурой, соответствующей интерфейсу. Как добавить метод с другой сигнатурой, но известным типом, соответствующей интерфейсу?

Редактировать:

Пример StackableItem: зелье x10

Пример UniqueItem: 3 пистолета с каждым имеют разные боеприпасы

IStackable предназначен для пользовательского интерфейса, так что пользовательский интерфейс не должен знать их реализация и, тем не менее, может соответственно отображать Item и Amount (и аккуратно превращаться в один слот Item независимо от реализации)

1 Ответ

4 голосов
/ 13 февраля 2020

Да, вы можете просто сделать

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

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

Я думаю, что вы хотели спросить: вы хотите быть уверены, что только StackableItem может быть передано, если это Метод реализован в StackableItem.

Я вижу в основном два варианта:

  • Проверка времени выполнения путем приведения. Либо используя 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)}");
        }
    } 
    
  • Используйте generi c интерфейс

    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;
        }
    }
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...