0

So in a challenge in class, we had to use a public abstract Class Cycle as the parent class and create subclasses off of it. I used Unicycle Class as an example. My professor refuses to let me put Color color as protected. He wants it private. He said the way that I can get the privacy issue worked out was by implementing the getter and setter for color. Initially they were set as abstract Color getColor() and abstract void setColor(Color color) but I tried implementing them inside the abstract class by making them public and giving them the method body.

The test in the code is:

cycle.setColor(Color.RED);
assertEquals(Color.RED, cycle.getColor());

I continue to get the error message, The field Cycle.color is not visible

I know it works with protected but I have to use private. Anyone have any hints they can throw at me here? I am going nuts with all of my research and failed trials.

public abstract class Cycle
{
    //Declare instance variables
    private String make;
    private Color color;
    //Create a constructor that only contains an argument for make
    public Cycle(String make)
    {
        
        this.make = make;
    }
    //Create a constructor that contains an argument for make and color
    public Cycle(String make, Color color)
    {
        
        this.make = make;
        this.color = color;
    }
    //Create getter and setter methods
    abstract int getNumberOfWheels();
    
    //*********Was abstract Color getColor();
    public Color getColor()
    {
        return color;
    }
    //*********Was abstract void setColor(Color color);
    public void setColor(Color color)
    {
        this.color = color;
    }
    final String getMake()
    {
        //return the make of the object
        return make;
    }

Unicycle Class

public class Unicycle extends Cycle
{
    
    //Create a constructor that only holds the argument make
    public Unicycle(String make)
    {
        //Call on the super (parent) class to create the object with arguments
        super(make);
        
    }
    public Unicycle(String make, Color color)
    {
        super(make, color);
    }
    //Create a method to get the number of wheels and return 1 since a unicycle only has 1 wheel
    public int getNumberOfWheels()
    {
        return 1;
    }
    
}
PresFelber
  • 61
  • 6
  • If `color`is a private field in `Cycle` and has public getters and setters in `Cycle` then why are you trying to override them in `Unicycle`? – khelwood Mar 15 '21 at 21:08
  • Eclipse naturally threw in the Override when I added the unimplemented methods. I apologize, I have been playing with this code every which was but Tuesday. – PresFelber Mar 15 '21 at 21:10
  • This is a test that fails, for instance. cycle.setColor(Color.RED); assertEquals(Color.RED, cycle.getColor()); – PresFelber Mar 15 '21 at 21:10
  • If `Cycle` provides `getColor` and `setColor` then `Unicycle` already has them. You don't need to define them again in `Unicycle`. – khelwood Mar 15 '21 at 21:11
  • Nothing in the test snippet you provided accesses the field mentioned in the error. Please provide a [mcve]. – Savior Mar 15 '21 at 21:28

2 Answers2

1

color is not visible to sub-classes since color is private in Cycle, so having a getter/setter in the Unicycle class results in a compilation issue.

Cycle already defines a getter/setter for color, and Unicycle is-a Cyle, so there's no need to attempt to override the getter/setter in sub-classes.

Remember that any public (or protected) method defined in a base class is available to sub-classes. This is one of the benefits of using inheritance.

Andrew S
  • 2,509
  • 1
  • 12
  • 14
  • Thank you, I fixed that in the code but still get the error. – PresFelber Mar 15 '21 at 21:18
  • What error? You'll need to provide more details/code. – Andrew S Mar 15 '21 at 21:21
  • The error is in the original post. I get the Field Cycle.color is not visible. I know making Color color protected fixes any and all issues but my Prof wants the Color color to be private under Cycle. – PresFelber Mar 15 '21 at 21:22
  • The updated code in the original question works for me - did you re-compile? As other commenters have mentioned, provide the complete code to reproduce the issue. – Andrew S Mar 15 '21 at 21:34
  • I had to restart my computer and Eclipse twice and now it works. Thank you for walking me through that although I think it should have been working in the first place. – PresFelber Mar 15 '21 at 21:39
  • "Remember that any public (or protected) method defined in a base class is available to sub-classes. This is one of the benefits of using inheritance." - No. This is not correct. Protected fields and methods are also available to classes in the same package. Therefore, it is not a benefit of inheritance. In fact, you can achieve almost everything with composition. – hfontanez Mar 15 '21 at 21:58
1

My professor refuses to let me put Color color as protected. He wants it private. He said the way that I can get the privacy issue worked out was by implementing the getter and setter for color.

In case you were wondering if he is being difficult, I can tell you that he is trying to teach you a very important concept of Object-Oriented Programming. And that is limiting the scope of your variables in this case. You don't EVER want to give direct access to the data members of a class unless they are CONSTANTS. There are a few reasons for it, one of which is in case you need to add preliminary steps in the future before returning the value (i.e. return a value from an alternate source).

Now, you have something like this:

public abstract class Parent {
    private String something;
    protected Parent() {
        something = "N/A";
    }

    protected String getSomething () {
        return something;
    }

    protected void setSomething (String something) {
        this.something = something;
    }
}

 public class Child extends Parent {

    // bad use of override
    @Override
    public void setSomething (String something) {
        super.setSomething(something);
    }

    // bad use of override
    @Override
    public String getSomething() {
        return something;
    }

    public static void main (String[] args) {
        Child child = new Child();
        child.setSomething("New value");
        System.out.println(child.getSomething());
    }
}

public class Unrelated {
    public static void main (String[] args) {
        Parent child = new Child();
        child.setSomething("Foo");
        System.out.println(child.getSomething());
    }
}

This works.... The field in the abstract class is private. Therefore, it is blocked from direct manipulation. The child classes can override a protected method of the abstract (parent) class and make it public for unrelated classes to call freely. I included a main method in both the child class and the unrelated class to illustrate this point.

The reason why the override is bad is because it doesn't do anything... HOWEVER, protected methods are restricted to be called outside the package or by classes unrelated to the class declaring the protected method. Therefore, if the unrelated class was outside of the package, it would not be able to call these protected methods. THEREFORE, you must override them by the child classes and make them public. THAT SAID, if this is the case, you could argue that the best thing is to make the protected method public in the parent class and avoid forcing implementing classes to override protected methods just for this reason.

hfontanez
  • 5,774
  • 2
  • 25
  • 37
  • 1
    @PresFelber I updated with more information that should make you understand the differences between `public` and `protected` methods, which I am sure is what your teacher wants you to learn. – hfontanez Mar 15 '21 at 21:48