I have the following classes:
class foo {
public void a() {
print("a");
}
public void b() {
a();
}
}
class bar extends foo {
public void a() {
print("overwritten a");
}
}
When I now call bar.b() I want it to call the overridden method a() in foo. It does, however, print "a".
Are your two classes in different packages? And is your foo class methods declared public, protected, or private or package local? Obviously if they are private, this won't work. Perhaps less obvious, is if they are package local (i.e. no public/protected/private scope) then you can only override them if you are in the same package as the original class.
For example:
package original;
public class Foo {
void a() { System.out.println("A"); }
public void b() { a(); }
}
package another;
public class Bar extends original.Foo {
void a() { System.out.println("Overwritten A"); }
}
package another;
public class Program {
public static void main(String[] args) {
Bar bar = new Bar();
bar.b();
}
}
In this case, you will still get 'A'. If you declare the original a() method in Foo public or protected, you will get the result you expected.
It may be that you are trying to use static methods, which won't work as they don't get overridden.
A good way of checking is to add the #Override annotation to bar.a() and see if the compiler gives you an error that a() isn't actually overidding anything
When I run the following:
public class Program {
public static void main(String[] args) {
bar b = new bar();
b.b();
}
}
class foo {
public void a() {
System.out.printf("a");
}
public void b() {
a();
}
}
class bar extends foo {
public void a() {
System.out.printf("overwritten a");
}
}
I get the following output:
overwritten a
which is what I would expect to see.
Are the methods defined as static? That's the only way I could see getting that result. I found a good explanation about that here: http://faq.javaranch.com/view?OverridingVsHiding
You may be confused if you are coming from C# or some other language where you have to explicitly declare virtual functions and/or overriding functions.
In Java, all instance functions are virtual, and can be overridden -- unless they are declared as private and/or final.
It is not necessary to specify the new #Override annotation to do so, adding the annotation just specifies that your intent is to override, and will cause a either a warning or error if it isn't an override. (If you accidentally misspelled the method name for example).
Andrew's example shows how this should work.
From the horse's mouth:
http://download.oracle.com/javase/tutorial/java/IandI/override.html
"The version of the overridden method that gets invoked is the one in the subclass. The version of the hidden method that gets invoked depends on whether it is invoked from the superclass or the subclass."
So if they are both static methods and you invoke the method from the super class, then the super class method is invoked, not the subclass method. So really, no overriding is taking place.
While I was working on an Android program, I had the same problem on my Java classes. It turned out that the problem was not in the classes but the way Android framework processes screen output.
for example if output was programmed in the onCreate() method in the parent class, Android failed to correctly fetch the output of overridden methods from child classes beyond first child. Honestly I don't understand whole method calling order.
To resolve the issue I simply programmed the output in the onResume() and now it seem to work fine.
Related
I'm a student, learning Java. I know, protected means access from children or the same package. Here we inherit and override a protected method. And after such an action, whenever the base class wants to call its own method it calls the new overridden one from the subclass. I've been debugging this for a while and marked the execution order with comments. But I can't understand why doesn't it call the base method when I clearly call that from inside the base class constructor?
public class Solution {
public static void main(String[] args) {
new B(); // first
}
public static class A {
public A() {
initialize(); // third
}
protected void initialize() {
System.out.println("class A"); // we never go here
}
}
public static class B extends A {
public B() {
super(); // second
initialize(); // fifth
}
protected void initialize() {
System.out.println("class B"); // fourth, sixth
}
}
}
That's a task from one website, so basically the solution is to change access modifier of the initialize method from protected to private. But I still fail to understand why is the problem happening.
What you're trying to do is defeat the purpose of polymorphism. You can, but you have to make the call specifically. Add a Boolean to your method and call the super.initialize(Boolean). Again, this defeats polymorphism and the extending class HAS to know about the super class. NOT VERY ELEGANT.
public class Solution {
public static void main(String[] args) {
new B(); // first
}
public static class A {
public static boolean USE_SUPER = true;
public A() {
initialize(USE_SUPER);
}
protected void initialize(boolean unusedHere) {
System.out.println("class A");
}
}
public static class B extends A {
public static boolean USE_EXTENDED = false;
public B() {
super();
initialize(USE_EXTENDED);
}
protected void initialize(boolean useSuper) {
if (useSuper)
super.initialize(useSuper);
else
System.out.println("class B");
}
}
}
As Dakoda answered, the root cause is polymorphism. That means we may create child objects, but refer to them as their parent type and when we call the methods of the parent layer we actually refer to the child's methods.
In my case, I create a child object (marked //first) B, which has its own body of the initialize method. One nuance of the inheritance is that it doesn't include constructors, so I can call the parent's constructor (marked //second). Inside the parent's constructor, I call the initialize method - that is the polymorphism because I call the method of the child from its parent abstraction layer.
Here is the answer to the question - this happens, because we only allocated memory for a B instance, that means, we took A as our base and started to extend it (while we can overwrite anything inside). The only two things we did are:
We created a constructor (it wasn't included in the base, as mentioned above)
We overwrote the initialize method code. The code for this method that is inside the base is now lost for this object.
This concept of polymorphism is designed that way and there is no way for us to access the base method unless we specifically create an object that is either A itself or a child that doesn't overwrite this method.
Lets say I have a class called 'Foo', with some methods:
public class Foo{
public void a(){
//stuff
}
public void b(){
//stuff
}
}
And i have an instance of Foo:
Foo instanceOfFoo = new Foo();
Can i remove the method 'a' from 'instanceOfFoo'?
You can't remove a method, not without changing the byte code and breaking the code's "contract", but you could extend the class and have the child class's method override throw an UnsupportedOperationException if called. Also the child class should deprecate the method, and explain in its javadoc the rationale behind it, and what to use in its place.
This would change the class's contract, but in a more responsible way then say fiddling with the byte code.
For example:
public class Foo {
public void a() {
// stuff
}
public void b() {
// stuff
}
}
public class FooChild extends Foo {
/**
* #deprecated: This method should no longer be used and will throw an exception
*/
#Override
#Deprecated
public void a() {
String text = "The method a is no longer supported";
throw new UnsupportedOperationException(text);
}
}
Short answer: No, not really.
Long answer: If you can control the ClassLoader being used to load the Foo class, you can intercept the request to load the Foo class and use ASM or Javassist to modify the class's bytecode before loading it.
public class Base {
public Base() {
foo();
}
public void foo() {
System.out.println("Base.foo()");
}
}
public class Derived extends Base {
public Derived () {}
public void foo() {
System.out.println("Derived.foo()");
}
}
And then, when i call those:
public class Running {
public static void main(String[] args) {
Base b = new Base();
Derived d = new Derived();
}
}
It outputs:
*Base.foo()*
*Derived.foo()*
So why, when it gets to derived constructor, it invokes the base constructor but uses the derived's method instead?
PS: If I mark those methods as private, it will print out:
*Base.foo()*
*Base.foo()*
This is how Java works read this page https://docs.oracle.com/javase/tutorial/java/IandI/super.html
And more specifically the Note here :
Note: If a constructor does not explicitly invoke a superclass
constructor, the Java compiler automatically inserts a call to the
no-argument constructor of the superclass. If the super class does not
have a no-argument constructor, you will get a compile-time error.
Object does have such a constructor, so if Object is the only
superclass, there is no problem.
So as you can see this is expected behavior. Even though you dot have a super call it is still automatically inserting it.
In regards of the second Question even though you are within the super constructor body still you Instance is of the Subtype. Also if you have some familiarity with C++ read this Can you write virtual functions / methods in Java?
The reason why it will write the base class when marking with private is because private methods are not Inherited. This is part of the Inheritance in Java topic.
To answer the question in your title. As I said, you cannot avoid the base class constructor being called (or one of the base class constructors if it has more than one). You can of course easily avoid the body of the constructor being executed. For example like this:
public class Base {
public Base(boolean executeConstructorBody) {
if (executeConstructorBody) {
foo();
}
}
public void foo() {
System.out.println("Base.foo()");
}
}
public class Derived extends Base {
public Derived() {
super(false);
}
public void foo() {
System.out.println("Derived.foo()");
}
}
public class Running {
public static void main(String[] args) {
Base b = new Base(true);
Derived d = new Derived();
}
}
Now the main method prints only:
Base.foo()
Because in the contructor of the Derived class it automatically gets injected a call to super(), if you do not add a call to super or to other constructor in the same class (using this).
Given this class:
abstract class Foo{
public Foo(){...}
public abstract void checkable();
public void calledWhenCheckableIsCalled(){
System.out.println("checkable was called");
}
}
Is there any code I can put in Foo's constructor to make calledWhenCheckableIsCalled get called when checkable is called?
Note: This is a gross simplification of an actual project I am working on.
Edit: I have already implemented a template pattern workaround. I just wondered if there was another way to do this I am missing. (Perhaps using reflection.)
Looks like a template method pattern.
But then you must implement Foo.checkable() and introduce another abstract method to delegate to.
abstract class Foo{
public Foo(){}
public void checkable(){
calledWhenCheckableIsCalled();
doCheckable();
}
protected abstract void doCheckable();
public void calledWhenCheckableIsCalled(){
System.out.println("checkable was called");
}
}
I would also suggest to make checkable() final in this case so that you can be sure that checkable() can not implemented in another way as you expected.
In addition to Brian Roach's comment
The downside is that the protected can be expanded to public in the subclass, so you can't explicitly enforce it.
That's true, but you can prevent a Foo instance from being instantiated if a subclass increases the visibility of doCheckable. Therefore you have to introduce a verification whenever an object is instantiated. I would recommend to use an initializer code so that the verification is executed on every constructor that exists. Then it can not be forgotten to invoke and therefore be by-passed.
For example:
abstract class Foo {
{ // instance initializer code ensures that enforceDoCheckableVisibility
// is invoked for every constructor
enforceDoCheckableVisibility();
}
public Foo() {...}
public Foo(Object o) {...}
private void enforceDoCheckableVisibility() {
Class<?> currentClass = getClass();
while (currentClass != Foo.class) {
try {
Method doCheckableMethod = currentClass.getDeclaredMethod("doCheckable");
if (Modifier.isPublic(doCheckableMethod.getModifiers())) {
throw new RuntimeException("Visibility of "
+ currentClass.getSimpleName()
+ ".doCheckable() must not be public");
}
} catch (SecurityException | NoSuchMethodException e) {}
currentClass = currentClass.getSuperclass();
}
}
}
Since the check is implemented using reflection the downside is that it is only checked at runtime. So you will not have compiler support of course. But this approach let you enforce that an instance of a Foo can only exist if it fulfills your contract.
No, the constructor will get invoked once during the object initialisation. You can however get your subclass that provides the implementation to call the method in the super class:
class Bar extends Foo {
// implementation of abstract method
public void checkable(){
super.calledWhenCheckableIsCalled(); // call to parent's method
...
}
}
EDIT
You could achieve this with aspects. Using an aspect you can intercept each call to a method by referring to the abstract parent method. This leaves you free from interfering eith the child code. Your calledWhenCheckableIsCalled code would then become part of the intercepting code.
abstract class Foo {
// use pointcut to intercept here
public void checkable();
}
There is no way as you are forcing that method to implement in child.
An awkward suggestion will be know from child implementation. I mean there is no clean way AFAIK
abstract class foo {
public abstract void bar();
public void moo() {
System.out.println("some code");
this.bar();
System.out.println("more code");
}
}
now if moo is called, the underlying implementation of bar will be used, it is just a small paradigm shift from what you want.
so your end user would call moo instead of bar, but he still needs to implement bar
Nope, an abstract method doesn't have a body. You could, however, chain your method like this:
abstract class Foo {
void callMeInstead() {
// do common
callMeImplementation();
}
abstract void callMeImplementation();
}
It looks to me like you're looking for the template pattern:
public abstract class Template {
public final void checkable() {
calledWhenCheckableIsCalled();
doCheckable();
}
protected abstract void doCheckable();
private void calledWhenCheckableIsCalled() {
System.out.println("checkable was called");
}
}
Now, each time checkable() is called, calledWhenCheckableIsCalled() is also called. And the suclass must still provide the actual implementation of checkable(), by implementing the doCheckable() method.
Note that making checkable() final prevents a subclass from overriding it and thus bypassing the call to calledWhenCheckableIsCalled().
I have the following problem in Java:
I have a base class and a derived class and I have a method in the base class. When I call the Base's foo method through Derived I want to get the Derived's class. The foo method can be generic if it can be done that way.
class Base
{
static void foo()
{
// I want to get Derived class here
// Derived.class
}
}
class Derived extends Base
{
}
Derived.foo();
Thanks for your help!
David
That's not the way that static methods work. You'll have to implement Derived.foo(), do whatever it is that's special to Derived, and that method then calls Base.foo(). If you really need the type information, you could create Base.foo0(Class klass).
But to be honest, any static method that needs to know that type of the class that it's invoked on should probably be an instance method.
Well, the caller of Derived.foo() knows what they are calling, so you could alter your methods thus:
class Base
{
static void foo(Class< T > calledBy)
{
// I want to get Derived class here
// Derived.class
}
}
class Derived extends Base
{
}
Derived.foo(Derived.class);
static methods are not inheritated. Static methods with the same signature can only hide similar methods in the superclass. This means that you never will see the result you probably want - you always exactly know the enclosing class. It is never possible that the static method is somehow "within" another class. So it is just impossible to produce the desired result. Calling a static method from a subclass or an instance is a bad idea for this reason as it just hides the real class. (IDEs and static code analysis tools can mark or correct this.)
Sources:
JLS http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#227961
http://docs.oracle.com/javase/tutorial/java/IandI/override.html
So what works with inherited methods does not work with static methods that are not inherited.
class Base {
static void foo() {
// Only the static context is available here so you can't get class dynamic class information
}
void bar() {
System.out.println(getClass());
}
}
class Derived extends Base {
}
class Another extends Base {
static void foo() {
// No super call possible!
// This method hides the static method in the super class, it does not override it.
}
void bar() {
super.bar();
}
}
Derived derived = new Derived();
derived.bar(); // "class Derived"
Base base = new Base();
base.bar(); // "class Base"
// These are only "shortcuts" for Base.foo() that all work...
derived.foo(); // non-static context
Derived.foo(); // could be hidden by a method with same signature in Derived
base.foo(); // non-static context
Base.foo(); // Correct way to call the method
Another a = new Another();
a.foo(); // non-static context
Another.foo();
Is it good idea that the language allows this? - Hm. I think it is telling that IDEs and code analysis tools warn and can even correct this automatically.
Not possible, Derived.foo() will simply give code for Base.foo().
Derived.foo();
This will go to foo defined in Derived, if one is defined there:
class Base {
static void foo() {
System.out.println("Base");
}
}
class Der extends Base {
static void foo() {
System.out.println("Der");
}
}
class Check {
public static void main(String[] args) {
Base.foo();
Der.foo();
}
}
When I run it:
javac -g Check.java && java Check
Base
Der
So what is your question? If you to require that each derived class implement foo that is not possible to enforce in Java.