【问题标题】:Using attributes in a class that implements an interface in another class在实现另一个类中的接口的类中使用属​​性
【发布时间】:2014-02-23 01:20:02
【问题描述】:

大家好,我正在尝试使用我的Fish class 中的属性,它实现了一个名为Catchable 的接口,在我的Fisher class 中,这是可能的,还是我不理解的接口的某些部分。因为我认为我们被允许在一个由接口实现的类中使用属​​性,在另一个类中,但是我一直在说:

Error: cannot find symbol
  symbol:   variable weight
  location: variable item of type Catchable

Error: cannot find symbol
  symbol:   variable size
  location: variable item of type Catchable

Error: cannot find symbol
  symbol:   variable weight
  location: variable item of type Catchable .

感谢您对此提供任何帮助或建议!

如果需要,这里是我的Catchable 界面:

public interface Catchable
{
  public float getWeight();
  public boolean isDesirableTo(Fisher f);
}

我的Fish class 实现了Catchable 接口

public abstract class Fish implements Catchable
{
    // Any fish below this size must be thrown back into the lake
    public static int  THROW_BACK_SIZE = 18; 
    public static float WEIGHT_LIMIT = 10;

    protected float weight;
    protected int  size;

    public Fish(int aSize, float aWeight) 
    {
        size = aSize;
        weight = aWeight;
    }


    public boolean isDesirableTo(Fisher f) 
    {
        if(canKeep() && f.numThingsCaught < f.LIMIT && this.weight + f.sumOfWeight < WEIGHT_LIMIT)
        {
          return true;
        }
        else
        {
        return false;
        }
    }

    public abstract boolean canKeep(); 

    public int getSize() { return size; }
    public float getWeight() { return weight; }


    public String toString () 
    {
        return ("A " + size + "cm " + weight +  "kg " + this.getClass().getSimpleName());
    }

}

最后是我的Fisher class

import java.util.*;

public class Fisher     
{
  private String name;
  private Catchable [] thingCaught;
  public int numThingsCaught; 
  private int keepSize;
  public float  sumOfWeight;
  public static int LIMIT = 10;

  public String getName() 
  {
    return this.name;
  }

  public int getNumThingsCaught()
  {
    return this.numThingsCaught;
  }

  public int getKeepSize()
  {
    return this.keepSize;
  }


  public Fisher(String n, int k)
  {
    name = n;
    keepSize = k;
  }

  public String toString()
  {
    return(this.name + " with " + this.numThingsCaught + " fish");
  }
  private ArrayList<Catchable> thingsCaught = new ArrayList<Catchable>();


  public void keep(Catchable item) 
  {
    if(this.numThingsCaught < LIMIT)
    {
      thingsCaught.add(item);
      numThingsCaught++;
      sumOfWeight += item.weight;
    }
  }

  public boolean likes(Catchable item)
  {
    if(item.size >= this.keepSize)
    {
      return true;
    }

    else 
    {
      return false;
    }
  }

  public void listThingsCaught() 
  {
    System.out.println(this.toString());

    for(Catchable item : thingsCaught)
    {
      System.out.println(item.toString());
    }
  }

  public void goFishingIn(Lake lake)
  {
    Catchable item = lake.catchSomething();

    if(likes(item))
    {
      this.keep(item);
    }
    else
    {
      lake.add(item);
    }
  }

  public void giveAwayFish(Fisher fisher, Lake lake)
  {
    for(Catchable item : thingsCaught)
    {
      if(fisher.likes(item))
      {
        fisher.keep(item);
      }
      else
      {
        lake.add(item);
      }
      sumOfWeight -= item.weight;
    }
    thingsCaught.clear();
    this.numThingsCaught = 0;

  }

}

【问题讨论】:

  • 出于好奇,您有 C# 的背景吗?

标签: java variables methods interface


【解决方案1】:

问题在于以下几行:

  • keep():

    sumOfWeight += item.weight;
    
  • likes():

    if(item.size >= this.keepSize)
    
  • giveAwayFish():

    sumOfWeight -= item.weight;
    

在任何情况下,item 的类型都是 Catchable,而 Catchable 没有 sizeweightfields。你需要做的是调用item.getWeight()而不是item.weight,并在Catchable中添加一个getSize()方法,然后调用item.getSize()而不是item.size

  • Catchable:

    public interface Catchable
    {
      public float getWeight();
      public int getSize();
      public boolean isDesirableTo(Fisher f);
    }
    
  • keep():

    sumOfWeight += item.getWeight();
    
  • likes():

    if(item.getSize() >= this.keepSize)
    
  • giveAwayFish():

    sumOfWeight -= item.getWeight();
    

您不必修改Fish,因为它已经实现了getSize()。 而且你真的应该使用像 Eclipse 这样的 IDE,因为它可以实时显示你的错误在哪里。

【讨论】:

    【解决方案2】:

    不是每个Catchable 都是Fish,所以,例如

    public boolean likes(Catchable item)
    {
        if(item.size >= this.keepSize)
    ...
    

    会失败,因为Catchable 没有size 成员(它也不能有成员变量,因为它是一个接口)。 item在这里是Catchable,不是fish

    当您使用接口时,您应该只通过接口(或它扩展的接口)中定义的方法与实例交互。

    【讨论】:

    • 所以你能把 size 属性移到 Catchable 中吗?
    • Catchable 不能有size 属性,但它可以有一个getter 方法getSize(),你可以在Fisher 类中使用它来代替size
    【解决方案3】:

    在 Java 中,我们通常称它们为“字段”而不是“属性”。

    无论如何,有几个问题。首先,在Fish 中将weight(例如)声明为protected。这是正确的做法,但这意味着在Fish 之外无法访问weight。所以你必须在Fish之外的一个班级里这样做:

    void example (Fish fish) {
        // System.out.println(fish.weight); // <- not allowed, weight is protected
        System.out.println(fish.getWeight()); // <- ok, getWeight() is public
    }
    

    这就是首先在Catchable 接口中提供像getWeight() 这样的公共getter 的目的(而且接口不能具有非静态非最终成员字段的事实)。底层实现是隐藏的——实现Catchable 的对象可能根本没有weight 字段,并且可能根据一些完全不同的规则集计算返回值。不过没关系,因为你是通过getWeight()访问的。

    其次,即使Fish.weightpublic,上述内容对于一般的Catchable 也没有任何意义; Catchable 没有名为 weight 的字段。 Fish 确实如此。因此,如果您通过 Catchable 类型的引用访问它,则无论如何都没有 weight

    确实提供Catchable.getWeight(),但是。该方法存在于所有Catchable 类型中。所以你必须用它来访问weight。所以在你的Fisher 你可以这样做:

    void example (Catchable catchable) {
        // System.out.println(catchable.weight); // <- not allowed, Catchable has no weight
        System.out.println(catchable.getWeight()); // <- ok, getWeight() is public and is in Catchable
    }
    

    我强烈建议您阅读官方Interfaces and Inheritance 教程。它可能会让您熟悉您所询问的一些概念。


    添加:

    您似乎有 C# 或其他具有类似“属性”概念的语言的背景 - 您提供了一个 getter/setter,但在语法上您仍然直接通过属性名称引用它(例如 fish.weight = 3 调用 @ 987654348@ 自动)。

    Java 中不存在此构造。您可以将 getter/setter 编写为成员方法,然后调用它们,这就是您所得到的。直接字段访问不会自动调用 getter/setter。你可以有这个:

    class Example {
         public int field;
         public void setSomething (int x) { ... }
         public int getSomething () { ... }
    }
    

    这就是你得到的。你可以这样做:

    Example x = ...;
    x.field = ...;
    ... = x.field;
    x.setSomething(...);
    ... = x.getSomething();
    

    但是你不能自动做这样的事情:

    x.setField(...);
    ... = x.getField();
    x.something = ...;
    ... = x.something;
    

    因此,如果您有这样的语言背景,那可能是您困惑的根源。您将需要进行调整。在Java中你必须明确;该语言以其低歧义和冗余度而著称。

    【讨论】:

    • 等一下。 Fishabstract。你不能只做new Fish()
    【解决方案4】:

    我在您的代码中看到了这一点:

    sumOfWeight += item.weight;
    

    在这里慢一点——你没有使用一个类的具体实例;您指的是界面。您会观察到该接口没有weight 的字段,因此您的编译失败。

    如果你想坚持使用界面,那么你需要改变一些东西。

    • 在您的界面中添加一个方法getWeight()

      public float getWeight();
      
    • 从您的 Fish 类中删除 abstract 声明(这只会伤害和混淆您)。

    • 然后,当您想要执行该求和运算时,您可以:

      sumOfWeight += item.getWeight();
      

    【讨论】:

    • 感谢回复,但我的界面不是已经有 getWeight() 方法了吗?
    • 是的,但你没有使用它。我相信我选择了它作为我能看到的最快的例子(因为它确实定义了它);您还想在界面中创建其他依赖于字段而不是界面中的 getter 的方法。
    猜你喜欢
    • 1970-01-01
    • 2015-02-03
    • 1970-01-01
    • 2022-11-28
    • 2020-11-21
    • 2021-05-16
    • 1970-01-01
    • 2016-04-28
    • 1970-01-01
    相关资源
    最近更新 更多