2

I have a Base class method, that I want to override in a Derived class.

The derived class method should be called whenever the method with the same name is accessed from "outside" or from the derived class. When acessing the method from inside the base class, I want the base class method to be used. Consider the following code:

public class TestBaseMethod
{
    static class Basic {
        public Basic()
        {
            Basic.this.doSomething(); // <<---- This should call Basic version
        }

        public void doSomething()
        {
            System.out.println("Doing something old");
        }
    }

    static class Derived extends Basic {
        Object ressource = new Object();

        @Override
        public void doSomething()
        {
            System.out.println("Doing something completely new");
            // ressource.toString(); // <<---- explosion
        }
    }

    public static void main(String[] args)
    {
        Basic d = new Derived();
        System.out.println("-------------------------------");
        d.doSomething(); // <<---- This should call Derived version
    }
}

I want the following output:

Doing something old
-------------------------------
Doing something completely new

But it produces this output:

Doing something completely new
-------------------------------
Doing something completely new

I thought that explicitly stating the base class name in Basic.this.doSomething(); should do that trick, but apparently it does not.

Obviously, I could declare a variable of type Basic inside a Derived class instead of Deriving, but that kind of defeats the idea that the Derived class "is-a" Basic class and would force me to write oneline-redirection methods to obtain the same interface.

Here is why I want to do that:

When writing base classes, I want to use methods where I have the guarantee that inside the base class, the methods that I wrote are used, because I do not want deriving classes to interfere with base class internals. To me, it makes sense from an encapsulation standpoint, but maybe I am wrong?

The Basic#doSomething() method can be called from the Basic() constructor. If the Derived#doSomething() method uses ressources from Derived, then those ressources will only be available after Derived construction. However: Derived construction finishes AFTER the superclass construction, which means that when Derived is constructed, the Derived#doSomething() is called in the Basic() constructor and it will access uninitialized data.

Is there a way around this?

fat-lobyte
  • 1,129
  • 1
  • 10
  • 16
  • 1
    You can prevent subclasses from overriding methods by making those methods `final` in your superclass. Or make those methods `private`, then they are not visible in subclasses. (Methods that should be used internally in a class only should be `private`). – Jesper Mar 26 '15 at 14:57
  • But I *want* them to be overriden. They should provide the same interface in the Derived class as they do in the Basic class. It's just that Derived methods should not break Basic Methods. – fat-lobyte Mar 26 '15 at 15:01

3 Answers3

5

Calling veritable methods from a constructor is a bad practice, more could be found here: On invoking overridable method from constructors

As for enforcing to call the base class method - it's impossible.

Community
  • 1
  • 1
Petr
  • 5,999
  • 2
  • 19
  • 25
3

Make an inner method in Basic for doSomething and call that directly:

static class Basic {
    public Basic()
    {
        doSomethingImpl();
    }

    public void doSomething()
    {
        doSomethingImpl();
    }

    private void doSomethingImpl()
    {
        System.out.println("Doing something old");
    }
}
Necreaux
  • 9,451
  • 7
  • 26
  • 43
1

What you want to do is bad, from a design point of view. A good design would be to declare two separate methods, one overridable and the other not (either final or private).

Necreaux
  • 9,451
  • 7
  • 26
  • 43
Giovanni
  • 543
  • 2
  • 11
  • Sometimes it happens when people override your methods in ways that were not considered. It may not be ideal, but I've had this happen a lot. – Necreaux Mar 26 '15 at 15:43
  • 1
    What I suggested is exactly what you too suggested in your answer: delcare one private method (not ovveridable) and another one overridable. – Giovanni Mar 26 '15 at 15:52
  • Fair enough, I missed that. – Necreaux Mar 26 '15 at 16:16