【问题标题】:How Can I get a value from a base class that has been declared as an Interface?如何从已声明为接口的基类中获取值?
【发布时间】:2013-09-16 19:50:32
【问题描述】:

这是一款基于 OOP 的角色扮演游戏。我在将对象作为接口处理时遇到了麻烦。

abstract class Items
{
   public string name { get; set; }

}

所有项目都有名称,这是我想要获得的属性。

interface Ieatable
{
   int amountHealed { get; set; }
}

会治疗一个玩家。

class Healers : Items, Ieatable
{

    private int heal;

    public int amountHealed
    {
        get { return heal; }
        set { heal = value; }
    }

    public Healers(int amount, string name)
    {
        heal = amount;
        base.name = name;
    }

}

这里是我处理可食用物品的地方。我浏览了玩家背包中的每件物品。然后我检查该项目是否可食用。然后是我正在努力的部分,检查玩家背包中的物品之一是否与作为参数传入的可食用物品相同。

public void eatSomethingt(Ieatable eatable)
    {
        foreach (Items i in items ) //Go through every item(list) in the players backpack
        {
            if (i is Ieatable && i.name == eatable.name) //ERROR does not contain definition for name
            {
                Ieatable k = i as Ieatable;
                Console.WriteLine(Name + " ate " + eatable.name); //Same ERROR here.
                life = life + k.amountHealed;
                items.Remove(i);
                break;
            }

        }

    }

【问题讨论】:

  • 在接口中定义Name属性
  • 该错误告诉您确切的问题是什么。 Ieatable 没有 name 的定义。你对什么感到困惑?
  • 尽量避免使用复数形式。所有项目的类别应为Item
  • 我想你是想说as Items,而不是as Ieatable
  • @EricLippert 不,i 已经属于 Items 类型,不是吗?

标签: c# oop interface abstract-class


【解决方案1】:

我会另外定义它。

// The base interface for all items.
public interface INamedItem
{
    string Name { get; set; }
}

// all classes are derived from INamedItem, so you can always have the Name property.
public interface IEatable : INamedItem
{
    int AmountHealed { get; set; }
}

public class Healers : Ieatable
{

    public string Name { get; set; }
    public int AmountHealed { get; set; }

    public Healers(int amountHealed, string name)
    {
        AmountHealed = amountHealed;
        Name = name;
    }

}

示例:

public void eatSomethingt(IEatable eatable)
{
    var eatItem = items.OfType<IEatable>.Where( item => item.Name == eatable.Name).FirstOrDefault();

    if (eatItem == null)
        return;

    life = life + eatItem.amountHealed;
    Console.WriteLine(Name + " ate " + eatable.name); //Same ERROR here.
    items.Remove(i);


}

【讨论】:

    【解决方案2】:

    您不需要更改您的设计,因为其他答案表明您的 EatSomething 方法可以工作。只需更改传递的类型:

    public void eatSomethingt(Healer healer)
    {
        foreach (Items i in items)
        {
            if (i is Ieatable && i.name == healer.name)
            {
                Ieatable k = i as Ieatable;
                Console.WriteLine(Name + " ate " + healer.name);
                life = life + k.amountHealed;
                items.Remove(i);
                break;
            }
        }
    }
    

    对此答案的警告是,您可能需要IEatable,而不是Item(或Healer)。但是,在这种情况下,您可能没有要比较的名称,因此需要一个单独的方法。

    您传递给方法的IEatable 来自哪里?我假设它源于鼠标单击库存项目,因此,您可以执行以下操作:

    public void eatSomethingt(Healer item)
    {
        Console.WriteLine(Name + " ate " + item.name);
        life = life + item.amountHealed;
        items.Remove(item);
    }
    

    【讨论】:

      【解决方案3】:

      在项目上创建接口

      interface IITems
      {
          string name { get; set; }
      }
      
      abstract class Items : IItems
      { ....
      

      然后在IEatable中使用

      public interface IEatable : IItems
      { ....
      

      然后是治疗师类:

      public class Healers : IEatable
      { ...
      

      那么你应该可以访问 IEatable 类型的 name 属性

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-07-24
        • 2011-09-15
        • 2014-03-23
        • 1970-01-01
        • 2013-08-08
        • 2013-04-13
        • 2017-06-19
        • 1970-01-01
        相关资源
        最近更新 更多