KJ3
KJ3

Reputation: 5298

Implementing Interfaces and Inheritance

I'm getting a bit confused on how interfaces and inheritance work in the implementation stage. Here's a quick ERD:

                                          <<interface>>
Animal                                    IColorChangable    
----------------------------              -----------------------
-color: int                               -----------------------
----------------------------              + changeColor()
----------------------------              -----------------------
         ^(Inheritance Triangle)             ^(Interface Triangle)
         |                                   |
         |                                   |
----------------------------------------------
Dog
----------------------------
-breed: string
----------------------------
+ getBreed()
----------------------------   

So here I have a dog that extends an Animal class, and also implements a ColorChangable interface. Now, the colorchangeable interface's job is to update the color, which is an attribute that belongs to animal, not Dog. So what is the correct way to update the color in the dog class? It's dog that implements color changable, not animal. Right now I have this:

public class Dog extends Animal implements IColorChangable
{
    private String breed;

    public Dog(int color, String breed)
    {
        super(color);
        this.breed = breed;
    }

    public void changeColor()
    {
        //How to have access to color?
    }
}

public interface IColorChangable
{
    public void changeColor();
}

Upvotes: 2

Views: 131

Answers (4)

Jason C
Jason C

Reputation: 40305

You basically have three options. Which you choose depends on your requirements, the complexity of your invariants, etc.

The first option is to declare color as protected in Animal, then you can access it directly in derived classes:

public class Animal { 
    protected int color;
    ...
}

public class Dog extends Animal implements IColorChangable {
    ...
    @Override public void changeColor () {
        color = ...;
    }
}

The second option is to declare it private in Animal, in which case you cannot access it directly with a subclass, but you can add a setter to Animal (optionally final, optionally protected, again depending on your rules). This is useful if, e.g., you want to implement common validation logic in the base class:

public class Animal { 
    private int color;
    ...
    protected final void setColor (int color) { // could be public, could be non-final
        this.color = color;
    }
}

public class Dog extends Animal implements IColorChangable {
    ...
    @Override public void changeColor () { 
        setColor(...);
    }
}

The third option is to consider the question: Can every animal's color be changed? (In your example, color is a property of a general Animal.) If so, then you can have Animal implement the interface instead:

public class Animal implements IColorChangable {
    private int color;
    ...
    @Override public void changeColor () {
        color = ...;
    }
}

public class Dog extends Animal {
    ...
}

It really depends on what you need to do.

BTW, it's not usually tradition in Java to start interface names with an I like it is in the COM API. Also we generally use "properties" rather than "attributes". :)

Upvotes: 2

Jerome
Jerome

Reputation: 219

color = 123;

But your attribute color must be set as public or protected.

If it's private, you will need to do a setter in your Animal class :

public void setColor(int color){
    this.color = color;
}

And then call it in your method :

setColor(color);

Upvotes: 1

Ima Miri
Ima Miri

Reputation: 967

So you only need to add setColor and getColor to your Animal class but you should define them as a public methods.

public void setColor(int color){
    this.color = color;
}

public int getColor(){
    return color;
}

Then in changeColor mthod you can fill color via setColor.

public void changeColor()
{
    setColor(10); //for example
}

Upvotes: 3

Christian Tapia
Christian Tapia

Reputation: 34146

Just access it as a normal member:

public void changeColor(int color)
{
    this.color = color;
}

Upvotes: 0

Related Questions