2

The title says it all.

I have a unique color in every derived class and it is declared static.

Its like this:

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



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

then i have an object S of type Candy

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;
       }
     }
   }
}

The Candy class dont have a member color, so i dont need to post it. The only importance of the Candy class is for polymorphism purposes. The code above is not tried, so if im not sure if it runs accordingly. How can i print the color of the candy?

paul
  • 372
  • 4
  • 17
  • 4
    That should not be static. – SLaks May 05 '15 at 15:58
  • 1
    Color is a property of the *object instance,* not of the *class.* If you still want to do this, provide a better example in your actual problem domain. – Robert Harvey May 05 '15 at 16:00
  • 1
    @RobertHarvey I thought it was the other way around? `color` is a class level field and not a property of the instance. – Chetan Kinger May 05 '15 at 16:01
  • 1
    @ChetanKinger: Nope. Classes don't have color. Color is a property of an object; using it as such avoids the entire problem of having to subclass to create new colors. – Robert Harvey May 05 '15 at 16:02
  • These shouldn't be static. – CaffeineToCode May 05 '15 at 16:03
  • @Chetan Kinger, what I think Harvey meant is , Color `should be a property` instead of Color `is a property` as in given example, `'color` is not a property of object which it was supposed to be. – Jimmy May 05 '15 at 16:04
  • @RobertHarvey, I understand what you are trying to convey. But saying that `color` is the property of an object instance to a Java developer may confuse them because when you say `instance`, you mean a particular instantiation of a class. `static` fields by definition are independent of an `instance` – Chetan Kinger May 05 '15 at 16:06
  • wait im going to paste my minimized code here. – paul May 05 '15 at 16:06
  • @PaulJabines Just post the `color` field from `Candy` class. That should be enough. – Chetan Kinger May 05 '15 at 16:09
  • @PaulJabines I still don't see the Candy class. Can you show the `color` variable in Candy class. – Chetan Kinger May 05 '15 at 16:29
  • 1
    @SLaks and @CaffeineToCode. I believe the OP's intention was that `color` should be represented by a constant. The implementation is wrong but the intention behind it is correct. See my answer. – Chetan Kinger May 05 '15 at 16:55

2 Answers2

7

Assuming that Candy class has a color variable, you can print the color of the candy by saying candy.color.

That being said, the statement candy.color is always going to print the value assigned to the color variable in Candy class. This is because runtime polymorphism only applies to instance methods. Fields (whether static or not) are resolved at compile time using the reference type.

You need to make the following changes to all your classes :

  1. Make Candy immutable. You can read about how to make a class immutable in this answer. Also add a getColor method in Candy
  2. Once you have made Candy immutable, you can instantiate them with the required color. E.g. : candies[0][0] = new Candy("blue");
  3. There is no need to have one Candy subclass per color. Instead, you can simply instantiate a new Candy object for each new color. E.g. candies[0][1] = new Candy("red");
  4. You can print the color of a Candy by saying candy.getColor()

That being said, you can also consider using an enum called Candy instead of a Candy class since it looks like all you want is a String constant that represents a color :

public enum Candy {
    RED,BLUE,GREEN;
}
Community
  • 1
  • 1
Chetan Kinger
  • 15,069
  • 6
  • 45
  • 82
  • 1
    Excellent answer that covers all the bases. +1. – Robert Harvey May 05 '15 at 17:14
  • 1
    You make very good points. However, what if different candies have different properties, and not just a different color? – Yanick Rochon May 05 '15 at 17:22
  • 2
    @YanickRochon Thanks. Candy can be extended if different candies have different properties. Any properties common to a Candy should be added to Candy. Alternately, any behavior that needs to be added to Candy can be provided through composition. I believe making Candy immutable in this case could be debated and using an enum would no longer make sense. This answer is only based on the limited code presented in the question – Chetan Kinger May 05 '15 at 17:39
  • 1
    @ChetanKinger sure, however if you provide a public constructor to receive an arbitrary color as a string, then you need some kind of validation elsewhere... otherwise any string can be passed and make the return value unpredictable. Or you use an `enum` in the constructor, or you are using some builder or factory method to construct your `Candy` instance. – Yanick Rochon May 05 '15 at 17:46
  • @YanickRochon The possibilities are endless (because we can't see the full code from the OP) and beyond the level that is expected from a discussion on this specific question :). – Chetan Kinger May 05 '15 at 17:48
2

You are not using static properties the right way. For once, you need the color of an instance of Candy, therefore an instance method should be just fine. Why do you have the constraint of using a member instead of a method? That, you are not saying.

A proper solution is inheritance. You should have Candy be an abstract class declaring your color method, and providing a controlled Color value instead of a string for comparison.

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; }
}

Then simply call

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

for the color of that candy instance.

The advantage of using an enum over a String is that you can compare them easily with == instead of relying to it's .equals method and, also, you minimize spelling mistakes.

Yanick Rochon
  • 51,409
  • 25
  • 133
  • 214
  • I did it this way using abstract class with abstract getter method thats why i said without using a getter. Also, i like to have it with string so that it is closed for modification but open for extension. With enum, i would change the class Candy before i could create another class which extends Candy. But +1 for stating that enums comparison performance is better than String at conditions. – paul May 06 '15 at 00:11