0

I'm trying to achieve the following:

I have a parent class, with some logic. In the child class, I "redefine" constants/properties. Is there any way to make the child properties accessible by methods defined in the parent class? Or to be more specific - is there any way to force the "out" method to write extended rather than base in the following example?

public class BaseTest {
    public static final String x = "base";

    public void out() {
        System.out.println(x);
    }
}

public class ExtendedTest extends BaseTest{
    public static final String x = "extended";
}

public class Main {
    public static void main(String[] args) {
        BaseTest base = new BaseTest();
        ExtendedTest extended = new ExtendedTest();
        base.out(); // base (as expected)
        extended.out(); // base (extended expected)
        System.out.println(extended.x); // extended (as expected)
    }
}

I come mainly from the world of PHP, where this approach works just fine. Dunno if I'm missing something or if the very design of Java does not allow this.

Thank you.

Note: This is not important whether the property is static or not. I just wanted to be able to override a property of any kind in a child class (just like I can override a method) which, on basis of the answers I've received so far, doesn't seem to be possible in Java. In PHP it is absolutely possible and that was why I asked the question.

Malis
  • 220
  • 2
  • 15
  • Possible duplicate of [What is polymorphism, what is it for, and how is it used?](https://stackoverflow.com/questions/1031273/what-is-polymorphism-what-is-it-for-and-how-is-it-used) – abdulwasey20 Feb 18 '19 at 09:30
  • Why is that a static field anyway? The most naive way to fix that would be a local field (not static) and an abstract method which returns the value of that field. – Tom Feb 18 '19 at 09:31
  • Possible duplicate of [What are the rules dictating the inheritance of static variables in Java?](https://stackoverflow.com/questions/9898097/what-are-the-rules-dictating-the-inheritance-of-static-variables-in-java) – Tom Feb 18 '19 at 09:32
  • 1
    You should, by the way, adhere to the Java Naming Conventions: constants (`static final` variables) should be in UPPER_SNAKE_CASE. – MC Emperor Feb 18 '19 at 09:32
  • The ExtenededTest class does not override the "out" method, therefore when being called from the child it prints the x from the parent. If you override the method "out" in the child to once again print x your program should print the x variable that is present in the child. – S.Tushinov Feb 18 '19 at 09:34
  • Static or not, that's not important, the point is to have the parent method access properties of the child class without having to replicate the logic. – Malis Feb 18 '19 at 09:37
  • In other words - as @S.Tushinov mentions, is there any way to not to have override the out method and still make it see the child properties? – Malis Feb 18 '19 at 09:38
  • It _obviously_ isn't possible, because there is no way to require properties in child classes. – Tom Feb 18 '19 at 09:42
  • @Tom Sure there is, as *properties* in Java are defined by methods. You simply add an abstract getter. – chrylis -cautiouslyoptimistic- Feb 18 '19 at 09:45
  • Well *"obviously"* - it is not about requiring a property in a child class but about being able to override existing properties. Just like I can override a method, I thought it would be possible to override a property (and it works perfectly in PHP). But I take is a no, this is not possible. – Malis Feb 18 '19 at 09:47
  • @chrylis But OP said he doesn't want an abstract method and an abstract method doesn't require a field in order to be implemented. – Tom Feb 18 '19 at 09:50
  • 1
    Malis, terminology is very important here: In Java, a property is defined by a getter and/or setter method, not by a *field* (member variable); certain properties don't even have a backing field but are calculated when needed. Field access (whether static or instance) is resolved at compile-time, so direct field references aren't affected by re-declaring another field of the same name. Methods are used for this in Java, period. – chrylis -cautiouslyoptimistic- Feb 18 '19 at 09:53
  • M'kay, got it... – Malis Feb 18 '19 at 09:57

2 Answers2

4

static fields are not subject to inheritance. The x in the body of the out() method refers to BaseTest.x. Since you are not overriding out(), the body of the out() method still prints the value of BaseTest.x.

MC Emperor
  • 22,334
  • 15
  • 80
  • 130
  • Like mentioned above, it is not about being static or not but about being defined in parent/child. In other words, is it possible to create basic logic in the parent class and reflect it changes implemented in the child? – Malis Feb 18 '19 at 09:40
1

Static members are resolved at compile-time, and adding an ExtendedTest.x does not affect the also-existing BaseTest.x, which is what the BaseTest#out() method is linked to.

To accomplish what you're wanting, you need an overridden method:

public class BaseTest {
    public String x() {
        return "base";
    }

    public final void out() {
        System.out.println(x());
    }
}

public class ExtendedTest extends BaseTest {
    @Override
    public String x() {
        return "extended";
    }
}

This pattern is commonly used with an abstract method in the base class or interface to require the subclass to define an attribute such as a name or a key.

chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
  • This was exactly what I wanted to avoid. But as long as it seems impossible to use my "PHP approach", I'll have to live my live without it :) Anyway, thank you for the clarification. – Malis Feb 18 '19 at 09:55
  • @Malis If you can explain in more detail the task you're actually trying to do, we may be able to help show more idiomatic Java. In general, properties are just transparently inherited from the superclass (`BaseTest#getX()`), and if the property's value needs to be changed, it's changed using the setter. – chrylis -cautiouslyoptimistic- Feb 18 '19 at 09:56
  • Well, comments are a little short but I'll try. Let's say I have a base class Vehicle and extended class Car. Vehicles have a "feature" wheels (which could be a normal property but usually a constant in PHP; and constants don't exist in Java hence static final...) In PHP, the base class can access the "shared" constant by `static::WHEELS` and the child class just contains `class Car extends Vehicle { const WHEELS = 4; }` It doesn't need a special constructor, no overriden methods, just one line and the entire logic is in the base class. I was looking for a similar behavior in Java. – Malis Feb 18 '19 at 10:23
  • @Malis You can either override methods or define a property `wheels` and set its value in the `Car` constructor. – chrylis -cautiouslyoptimistic- Feb 18 '19 at 17:10