6

I want to call a method of an abstract class from abstract class called by inherit class.

Abstract class:

public abstract class Abstract {
    protected void updateMotionY(float deltaTime) {
        System.out.println("Abstrcat updateMotionY");
    }
    public void update(float deltaTime) {
        this.updateMotionY(deltaTime);
    }
}

Inherit class:

public class Obj extends Abstract {
    @Override
    protected void updateMotionY(float deltaTime) {
        System.out.println("updateMotionY");
        super.updateMotionY(deltaTime);
    }
    @Override
    public void update(float deltaTime) {
        super.update(deltaTime);
    }
}

Main method class:

public static void main(String[] args) {
    (new Obj()).update(10.0f);
}

Whenever I try to call new Obj().update() method in main class, it prints "updateMotionY" and "Abstrcat updateMotionY". I want to get only "Abstrcat updateMotionY".

Can anyone tell me how to resolve this problem?

Alex M
  • 2,756
  • 7
  • 29
  • 35
Amadeus
  • 63
  • 1
  • 7
  • 2
    *"it throws: updateMotionY and Abstrcat updateMotionY"* No, it doesn't, that isn't what exceptions (things you "throw") look like. Do you mean it *outputs* that? And if so, why does that surprise you? You're telling it to. – T.J. Crowder Aug 16 '17 at 12:02
  • 2
    The override of `update()` in the `Obj` class is redundant. – CloudPotato Aug 16 '17 at 12:03
  • It shows in console updateMotionY and Abstrcat updateMotionY. Both methods are called. I want to call only abstract method. – Amadeus Aug 16 '17 at 12:05
  • 1
    Use proper terms: "throws" refers to exceptions or errors. You mean "prints" or "displays". – RealSkeptic Aug 16 '17 at 12:05
  • thanks for the advaise I corrected thread – Amadeus Aug 16 '17 at 12:33

4 Answers4

4

I think you are using abstract in a very wrong way. Your base class should rather look like this:

public abstract class Abstract {
  protected abstract void updateMotionY(float deltaTime);

  public final void update(float deltaTime) {
    this.updateMotionY(deltaTime);
  }
}

Notes:

  • there is no point putting print "is abstract" into an abstract method. The java language has a keyword to express this fact.
  • subclasses should only be about implementing the abstract method(s) (probably in different ways). You absolutely do not want that subclasses change the implementation of other methods of the base class. Your base class defines a contract - and subclasses should adhere to that (as outlined by the Liskov Substitution Principle).

In other words: put the common parts solely in the base class, and make sure that you have to necessary abstract methods in there to do that. But avoid implementing methods more than once. That only leads to confusion and strange bugs.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
3

(new Obj()).update(10.0f) calls Obj::update which calls Abstract::update which calls this.updateMotionY. Because this is an instance of Obj, this calls Obj::updateMotionY.

This prints "updateMotionY".

This then calls super.updateMotionY(deltaTime) which is Abstract::updateMotionY.

This prints "Abstrcat updateMotionY".

That's the end of the call hierarchy and everything unwinds.


Fundamentally your confusion seems to stem from the fact that this.updateMotionY(deltaTime); in the Abstract class resolves to updateMotionY in the Obj class. That's basically the whole point of polymorphism.


One thing you could do is to add a private method (so that it cant be overridden) which contains the actual implementation, and defer to it:

public abstract class Abstract {
    private void motionY(float dt)
    {
        System.out.println("Abstrcat updateMotionY");
    }

    protected void updateMotionY(float deltaTime) {
        motionY(deltaTime);
    }
    public void update(float deltaTime) {
        motionY(deltaTime);
    }
}
Michael
  • 41,989
  • 11
  • 82
  • 128
0

If you only want to execute the abstracts superclass' method, then the simple solution is to just call super.updateMotionY instead of super.update in your Obj class

public class Obj extends Abstract {
    @Override
    protected void updateMotionY(float deltaTime) {
        System.out.println("updateMotionY: ");
        super.updateMotionY(deltaTime);
    }
    @Override
    public void update(float deltaTime) {
        super.updateMotionY(deltaTime);
    }
}
Steven Laan
  • 190
  • 10
0

You cannot create an instance of Abstract class so you're creating an instance of Obj class. Since your requirement is only to call method of Abstract class then why did you override the method updateMotionY

For your requirement this is what you need to do Abstract class:

public abstract class Abstract {
    protected void updateMotionY(float deltaTime) {
        System.out.println("Abstrcat updateMotionY");
    }
    public void update(float deltaTime) {
        this.updateMotionY(deltaTime);
    }
}

Inherit class:

public class Obj extends Abstract{
    /*@Override
    protected void updateMotionY(float deltaTime) {
        System.out.println("updateMotionY");
        super.updateMotionY(deltaTime);
    }*/
    @Override
    public void update(float deltaTime) {
        super.update(deltaTime);
    }
}

I have commented the overridden code which will give you the required result. Also, the answer given by https://stackoverflow.com/users/8466177/steven-laan will also work.

Nauman Shah
  • 342
  • 2
  • 12