user480884
user480884

Reputation: 3

Inheritance in Java

Consider the following code in Python:

class A(object):
    CLASS_ATTRIBUTE = 42

    def f(self):
        return "CLASS_ATTRIBUTE: %d" % self.CLASS_ATTRIBUTE

class B(A):
    CLASS_ATTRIBUTE = 44

Now A().f() and B().f() return "CLASS_ATTRIBUTE: 42" and "CLASS_ATTRIBUTE: 44" respectively.

How can I achieve a similar effect in Java? I want a CLASS_ATTRIBUTE field to be initialized statically and redefined in the inherited class but the f method should be only defined in the base class.

Upvotes: 0

Views: 253

Answers (5)

L. Cornelius Dol
L. Cornelius Dol

Reputation: 64036

You can't do this directly with only a variable, because in Java variables cannot override (they only shadow the super classes variables).

You need to use a protected "getter" method, which can then be overridden by the subclass:

class A
{
private int attribute=42;

...

protected int getAttribute() {
    return attribute;
    }
}

class B
extends A
{
private int attribute=44;

...

protected int getAttribute() {
    return attribute;
    }
}

But note there's a special consideration to calling methods from an object's constructor, in that it allows object code to run before object construction is complete.

Upvotes: 1

aioobe
aioobe

Reputation: 421040

Short answer: you cant solve it like this in Java. You'll have to solve it in another way.

In Java you can't override or "redeclare" fields in subclasses, and you can't override static methods.

It can be solved using an ugly reflection-hack (should be avoided though):

public class Main {
    public static void main(String... args) {

        A a = new A();
        B b = new B();

        System.out.println(a.f());             // Prints 42.
        System.out.println(a.fReflection());   // Prints 42.
        System.out.println(b.f());             // Prints 42.
        System.out.println(b.fReflection());   // Prints 44.
    }
}

class A {
    static int CLASS_ATTRIBUTE = 42;

    public int f() {
        return CLASS_ATTRIBUTE;
    }

    public int fReflection() {
        try {
            return getClass().getDeclaredField("CLASS_ATTRIBUTE").getInt(null);
        } catch (Exception wontHappen) {
            return -1;
        }
    }
}

class B extends A {
    // Compiles, but will not "override" A.CLASS_ATTRIBUTE.
    static int CLASS_ATTRIBUTE = 44;
}

Upvotes: 3

Stephen P
Stephen P

Reputation: 14800

This way of doing it introduces as little intrusion as I could think of. setAttribute() could be named something like setDefaultValue() if that's clearer.

public class A
{
    protected int attribute;

    public A()
    {
        setAttribute();
    }

    public String f()
    {
        return "CLASS_ATTRIBUTE: " + attribute;
    }

    protected void setAttribute()
    {
        attribute = 42;
    }
}


public class B extends A
{
    @Override
    protected void setAttribute()
    {
        attribute = 44;
    }
}


public class Main
{
    public static void main(String[] args)
    {
        A a = new A();
        B b = new B();
        System.out.println("A: " + a.f());
        System.out.println("B: " + b.f());
    }
}

Upvotes: 0

dpatchery
dpatchery

Reputation: 508

I'm not sure if you meant "statically" literally or not, but here's a brief example of how inheritance at it's most basic form looks in Java. Note that using a getter method to access the variable is a better idea for several reasons -- this is just an example.

public class Dog {
  protected String whatISay = "Woof!";
  public void speak(){
    System.out.println(whatISay);
  }
}


public class Poodle extends Dog {
  public Poodle(){
    whatISay = "Yap!";
  }
}


public class Main {
  public static void main(String[] args){
    Poodle fluffy = new Poodle();
    fluffy.speak();
    Dog dog = new Dog();
    dog.speak();
  }
}


Yap!
Woof!

Upvotes: 0

kkress
kkress

Reputation: 807

Is there a particular reason you want the attribute to be static? In Java the typical way you'd do this is to have A contain a protected variable that you then set in the constructors of the 2 classes:

public class A 
{
   protected int CLASS_ATTRIBUTE;
   public A()
   {
      CLASS_ATTRIBUTE = 42;
   } 

   public String f()
   {
      return "CLASS_ATTRIBUTE: " + CLASS_ATTRIBUTE;
   }

}

public class B extends A
{
   public B()
   {
      CLASS_ATTRIBUTE = 44;
   }
}

Alternatively (and probably more consistent with Java design patterns) you'd declare a function that you can override to return the value instead of using a member variable.

Upvotes: 3

Related Questions