Reputation: 886
Consider this following code:
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
}
}
I think it would be bad to add AddItem(IStackable stackable) to the interface. Even if I did, I can't make method that works as intended.
The only way I can think is to cast Stackable to Unique Items first, but I believe that's not a good way also.
*I think the best way is to add a method with different signature conforms to interface, So How to add method with different signature, but known type, conforms to interface?
Edit:
StackableItem example: Potion x10
UniqueItem example: 3 gun with each have different ammo
IStackable is for the UI, so that UI don't need to know their implementation and still can show the Item and Amount accordingly, (and neatly become one Item slot regardless of implementation)
Upvotes: 0
Views: 85
Reputation: 90852
Yes you could simply do
public interface IStackable
{
Item GetItem();
int GetAmount();
void AddItem(int amount);
void AddItem(IStackable item);
}
My guess what you wanted to ask is: You want to be sure that only StackableItem
can be passed if this method is implemented in StackableItem
.
I see basically two options:
Runtime check by casting. Either using 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)}");
}
}
or 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)}");
}
}
Use a generic interface
public interface IStackable
{
Item GetItem();
int GetAmount();
void AddItem(int amount);
}
public interface IStackable<T> : IStackable where T : IStackable
{
void AddItem(T item);
}
and let your class inherit
public class StackableItem : IStackable<StackableItem>
{
...
public void AddItem(StackableItem stackable)
{
_amount += stackable.GetAmount();
}
public void AddItem (int amount)
{
_amount += amount;
}
}
Upvotes: 4