【问题标题】:How to access derived class static member without using a getter?如何在不使用 getter 的情况下访问派生类静态成员?
【发布时间】:2015-05-06 08:53:06
【问题描述】:

标题说明了一切。

我在每个派生类中都有一个唯一的颜色,它被声明为静态的。

是这样的:

    class CandyBlue extends Candy
   {
      public static final String color = "blue";
   }



 class CandyRed extends Candy
   {
      public static final String color = "red";
   }

然后我有一个 Candy 类型的对象 S

class CandyFrenzy
{ 
   Candy candies[][];
   public CandyFrenzy()
   {
    candies = new Candy[4][4];
    candies[0][0] = new CandyBlue();
    candies[0][1] = new CandyRed();
    ....
   }

   public static void main(String args[])
   {
     CandyFrenzy candyFrenzy = new CandyFrenzy();
      Candy candy;
     for(int a=0; a<4; a++)
     {
       for(int b=0; b<4; b++)
       {
          candy = candies[a][b];
          //print the color of the candy;
       }
     }
   }
}

Candy 类没有成员颜色,所以我不需要发布它。 Candy 类的唯一重要性是用于多态性目的。 上面的代码没有尝试过,所以如果我不确定它是否相应地运行。 如何打印糖果的颜色?

【问题讨论】:

  • 那不应该是静态的。
  • Color 是 object 实例的属性, 不是 类的属性。 如果您仍想这样做,请在您的实际问题域。
  • @RobertHarvey 我以为是相反的? color 是类级别字段,而不是实例的属性。
  • @ChetanKinger:不。类没有颜色。颜色是对象的属性;这样使用它避免了必须子类来创建新颜色的整个问题。
  • @SLaks 和@CaffeineToCode。我相信 OP 的意图是 color 应该用一个常数来表示。实现是错误的,但其背后的意图是正确的。看我的回答。

标签: java


【解决方案1】:

假设Candy 类有一个color 变量,你可以通过说candy.color 来打印糖果的颜色。

话虽如此,语句candy.color 总是会打印分配给Candy 类中color 变量的值。这是因为运行时多态性仅适用于实例方法。字段(无论是否static)在编译时使用引用类型解析。

您需要对所有类进行以下更改:

  1. 使Candy 不可变。您可以在this 答案中了解如何使类不可变。还要在Candy 中添加一个getColor 方法
  2. Candy 设置为不可变后,您可以使用所需的颜色来实例化它们。例如。 :candies[0][0] = new Candy("blue");
  3. 每个color 不需要有一个Candy 子类。相反,您可以简单地为每个新的color 实例化一个新的Candy 对象。例如。 candies[0][1] = new Candy("red");
  4. 您可以通过说candy.getColor() 来打印Candycolor

话虽如此,您也可以考虑使用名为 Candyenum 来代替 Candy 类,因为看起来您想要的只是一个表示 color 的字符串常量:

public enum Candy {
    RED,BLUE,GREEN;
}

【讨论】:

  • 涵盖所有基础的优秀答案。 +1。
  • 你提出了很好的观点。但是,如果不同的糖果有不同的属性,而不仅仅是不同的颜色呢?
  • @YanickRochon 谢谢。如果不同的糖果有不同的属性,糖果可以扩展。 Candy 的任何通用属性都应该添加到 Candy 中。或者,任何需要添加到 Candy 的行为都可以通过组合来提供。我相信在这种情况下让 Candy 不可变可能会引起争议,并且使用枚举不再有意义。此答案仅基于问题中提供的有限代码
  • @ChetanKinger 当然,但是如果您提供一个公共构造函数来接收任意颜色作为字符串,那么您需要在其他地方进行某种验证......否则可以传递任何字符串并生成返回值不可预料的。或者您在构造函数中使用enum,或者您正在使用一些构建器或工厂方法来构造您的Candy 实例。
  • @YanickRochon 可能性是无穷无尽的(因为我们无法从 OP 中看到完整的代码),并且超出了对这个特定问题的讨论所期望的水平:)。
【解决方案2】:

您没有以正确的方式使用static 属性。一次,您需要Candy 实例的颜色,因此实例方法应该就可以了。为什么你有使用成员而不是方法的约束?那个,你不是说。

一个合适的解决方案是继承。你应该让Candy 是一个抽象类,声明你的颜色方法,并提供一个受控的Color 值而不是一个字符串来进行比较。

abstract class Candy {
    public static enum Color {
        RED,
        BLUE,
        ORANGE_WHITE_STRIPES,
        ...
    }

    public abstract Candy.Color getColor();
}

class CandyBlue extends Candy {
    public Candy.Color getColor() { return Candy.Color.BLUE; }
}

class CandyOrangeSpecial extends Candy {
    public Candy.Color getColor() { return Candy.Color.ORANGE_WHITE_STRIPES; }
}

然后简单地调用

Candy.Color candyColor = candies[a][b].getColor();

该糖果实例的颜色。

String 相比,使用enum 的优势在于,您可以轻松地将它们与== 进行比较,而不是依赖它的.equals 方法,而且还可以最大限度地减少拼写错误。

【讨论】:

  • 我是用抽象类和抽象 getter 方法这样做的,这就是为什么我说不使用 getter。另外,我喜欢将它与字符串一起使用,以便它对修改关闭但对扩展开放。使用枚举,我会在创建另一个扩展 Candy 的类之前更改 Candy 类。但是 +1 表示枚举比较性能在条件下优于字符串。
猜你喜欢
  • 1970-01-01
  • 2013-12-05
  • 1970-01-01
  • 2018-11-30
  • 2012-05-17
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
  • 2022-08-17
相关资源
最近更新 更多