Urbanleg
Urbanleg

Reputation: 6532

Dynamic invocation - java with interface and abstract class

I have this

public interface ICool {
   public boolean isCool();
}

Now i got this hierarchy:

public abstract class AbstractCoolness implements ICool{
   private isCool;

    @Override
    public boolean isCool() {
       return this.isCool;
    }
}

and

public abstract class CoolPeople extends AbstractCoolness {
   protected boolean isCool= true;
}

and

public abstract class UnCoolPeople extends AbstractCoolness {
   protected boolean isCool= false;
}    

Now I have a lot of classes that inherit from either UnCoolPeople or CoolPeople.

When I call them with this function:

if (person instanceof ICool ) {     
     if (person.isCool()) {
         // do something
     }
}

Problem is whenever this person.isCool() being invoked it is calling the abstractCoolness class and returns this.isCool which is alwayes false.

Any ideas why when I use this function on a person that extends from CoolPeople I still get isCool() == false?

Upvotes: 1

Views: 126

Answers (3)

Raffaele
Raffaele

Reputation: 20885

I guess AbstractCoolness is really

public abstract class AbstractCoolness implements ICool {

    private isCool;

    @Override
    public boolean isCool() { // Not isShared
       return this.isCool;
    }
}

In this case isCool() returns the content of the private variable isCool, which is initialized to false. If it were protected and not hidden (redeclared) by subclasses, it would work as you expect:

AbstractCoolness implements ICool {
  protected boolean cool;
  public boolean isCool() { return cool; }
}

CoolPerson extends AbstractCoolness {
  public CoolPerson() { cool = true; }
}

Upvotes: 1

Jeroen Vannevel
Jeroen Vannevel

Reputation: 44449

It's very simple. This code will return the value of isCool:

public abstract class AbstractCoolness implements ICool{
   private isCool;

    @Override
    public boolean isCool() {
       return this.isCool;
    }
}

Whereas this code will simply set a new variable called isCool in a subclass and hide the base member that's found in AbstractCoolness.

public abstract class CoolPeople extends AbstractCoolness {
   protected boolean isCool= true;
}

The method isCool() will always return the isCool variable defined in AbstractCoolness, the other won't affect it. Since the default value of a boolean is false, it will never return true.

You can bypass this by creating a constructor in your baseclass that takes a boolean isCool and pass it trough the constructor of a subclass.

A very quick sketch of the solution:

abstract class AbstractCoolness {
  private isCool;

  public AbstractCoolness(bool iscool){
     isCool = iscool;
  } 

  public boolean isCool() {
      return this.isCool;
  }
}

class CoolPerson extends AbstractCoolness {
   public CoolPerson() {
     super(true);
   }
}

Upvotes: 3

BobTheBuilder
BobTheBuilder

Reputation: 19294

You cannot "override" member value.

In your code, AbstractCoolness.isCool() return the value of its private member isCool, which is set to false by default.

You can either set isCool in a constructor or override isCool() method in your different concrete classes to return expected value.

Upvotes: 1

Related Questions