How to by-pass inheritance in java when invoking a method - java

class Super {
public void anotherMethod(String s) {
retValue(s)
}
public String retValue(String s) {
return "Super " + s;
}
}
class Sub extends Super {
public void anotherMethod(String s) {
retValue(s)
}
public String retValue(String s) {
return "Sub " + s;
}
}
if suppose in main,
Super s = new Sub();
s.anotherMethod("Test");
Output will be, Sub Test
Can you anyone help me in telling how to get output Super Test with the given sequences in main.
And let me explain why I want this, say I have a class which has method test() and it can be overriden by sub classes, in some cases I want the overriden test() and in some cases I want the test() of super class itself, there are many ways to do this, best suggestions will be helpful.

Why would you ever want to do that ??
The whole point of polymorphism is to call the right method without the need to know which kind of instance you've got ...

Whenever I find myself asking (or being asked) a question like this, I know, categorically, that I have made a mistake in my design and/or my object definitions. Go back to your object hierarchy and check, double-check and triple-check that every inheritance relationship represents an "IS-A", and not a "HAS-A" or something even weaker.

And let me explain why I want this,
say I have a class which has method
test() and it's can be overriden by
sub classes, some cases I want the
overriden test() and in some cases
test() of super class itself, there
are many ways to do this, it will be
helpful if anyone can be best
solution.
If your subclass overrides test(), then it overrides test() - this is the whole point of object inheritance. You just call methods on the object, which are dynamically resolved to the appropriate implementation based on the object's runtime class. That's the beauty of polymorphic typing, in fact, the caller doesn't have to know about any of this at all, and the subclasses determine how their behaviour differs from the superclass.
If you sometimes want it to act as its superclass method and sometimes want it to act as its subclass method, then you need to provide the context required to do this. You could either define two test-type methods; one which is never overridden and so always returns the superclass' behaviour (you can even mark the definition with final to ensure it's not overridden), and your normal one which is overridden as appropriate by the subclasses.
Alternatively, if there is some contextual information available, you can let the subclasses decide how to handle this; their implementation(s) could check some proeprty, for example, and based on that decide whether to call super.test() or proceed with their own overridden implementation.
Which one you choose depends on conceptually whether your main method (i.e. the caller), or the (sub)class objects themselves, are going to be in the best position to judge whether the superclass' method should be called or not.
But in no case can you override a method and expect it to magically sometimes not be overridden.

You would have to go the route of:
Super s = new Super();
s.anotherMethod("Test");
...but that will defeat the purpose of inheritance if you also need whatever Sub's got. You could hack it like below but this seems an unelegant way to do it.
class Sub extends Super {
public String anotherMethod( String s, boolean bSuper ) {
if( bSuper )
return super.retValue(s);
else
return retValue(s);
}
public String retValue(String s) {
return "Sub " + s;
}
}

From class Sub you can call super.anotherMethod("bla"), but you cannot access the method of the superclass in your main method - that would be against the whole idea of using subclasses.

The runtime type of s is Sub, so you're only ever calling methods on that class.

Whilst I agree with the other posters that this is not the best idea in the world, I believe it could be done with a little bit of tinkering.
If your child class was defined as:
class Sub extends Super {
public void anotherMethod(String s) {
retValue(s)
}
public void yetAnotherMethodString s) {
super.retValue(s)
}
public String retValue(String s) {
return "Sub " + s;
}
}
and then call this new method in your main you would be able to print out "Super Test".
Doesn't seem like a very good plan tho. If you want access to parent functionality from a child class then don't override your parent method, just write a new one!

I'm hesistant to post this as an answer, since the question is quite horrible - but static methods would do roughly what the OP seems to want. Specifically, they are resolved on the compile-time declared class of the variable, not on the class of the instance held within that variable at runtime.
So modifying the original example:
class Super {
public static void staticMethod(String s) {
System.out.println("Super " + s);
}
}
class Sub extends Super {
public static void staticMethod(String s) {
System.out.println("Sub " + s);
}
}
public static void main(String[] args) {
Super s = new Sub();
s.staticMethod("Test");
}
then main() will print out "Super test".
But still don't do this until you understand why you want to, and you recognise that you are introducing subclasses and then gratuitously working around the point of them being there. Most IDEs for example will flag the above example with lots of warnings, saying that you shouldn't call static methods on instance variables (i.e. prefer Super.staticMethod("Test") instead of s.staticMethod("Test")), for exactly this reason.

You cannot modify Sub or Super directly? If you could control what instance of Sub is used you could do something like:
Super sub = new Sub() {
#Override
public String retValue() {
// re-implement Super.retValue()
}
};
otherObject.use(sub);
Of course this requires you to have or be able to reproduce the source code of Super.retValue() and for this method not to use anything you can't access from an anonymous child. If the API is this badly designed though, you might do well to think about changing it out for something else.

Can you anyone help me in telling how
to get output "Super Test" with the
given sequences in main.
Don't overwrite anotherMethod() and retValue() in Sub in the first place.
In Sub.anotherMethod(), return super.retValue(s) instead of retValue(s).

Related

How to access base class method?

Simplified demo code to show my problem.
class Base {
public String toString() { return "Base"; }
};
class A extends Base {
public String toString() { return "A"; }
};
class Test {
public void test1() {
A a = new A();
Base b = (Base)a; // cast is fine, but b is the same instance as a
System.out.println(b.toString()); // want "Base", but get "A"
}
private String testB(Base b) {
return b.toString(); // this should return "Base"
}
public void test2() {
System.out.println( testB(new A()) ); // want "Base", but get "A"
}
};
I tried the cast approach (test1) , and the helper method (test2).
Up to now, I found to need a copy constructor for Base to create a real Base object.
Is there a method that does not need a duplicate object?
Some background info:
I get an instance of A, and I know its base class has a nice method, which I'd like to use instead of the overwritten version. I'd prefer to neither modify class A nor B (although a copy c'tor were a good enhancement anyway ;) )
From class A directly, you can use super.toString(); to execute toString() on Base.
However, from outside class A, you can't call the superclass implementation in this way, doing so would break encapsulation. If you want to expose the superclass implementation then you still can, but you have to provide a separate method on A that exposes it directly.
Even using a trivial reflection based approach, you still won't be able to access it:
If the underlying method is an instance method, it is invoked using dynamic method lookup
System.out.println(Base.class.getMethod("toString", null).invoke(new A(), null)); //Prints "A"
...and using MethodHandles.lookup().findSpecial won't work either from outside the child class, as that has to be invoked where you have private access (otherwise you'll just get an IllegalAccessException.)
I concede that there may well be some weird and wonderful way of doing it directly in Java that I haven't thought of without bytecode manipulation, but suffice to say even if you can do it that way, you certainly shouldn't for anything but a quirky technical demonstration.
You need to create the B instance(copy constructor), if you are using the A instance you will always get "A" no matter if you cast it or no.

Approach doing the same stuff on different objects

I am currently making a library which is an utility for me to handle something which is not associated with the question (I am implicitly not saying the subject because it is not really important), however it does use reflection.
I am retrieving all declared and inherited methods from a class, which currently works fine and is not the issue. But the thing is, I need to do this as well for sub-classes since those inherit over like methods do (however you cannot override those like methods).
The problem that I am facing that it will use the same algorithm but there will be on difference, instead of calling clazz.getDeclaredMethods() I need to call clazz.getMethods. What is the best way too approach this, and I kind of need to return Class[] and Method[] in the method signature as well.
Normally I would look for a shared superclass, but in this case I prefer to the have Class[] and Method[] accordingly. For starters, I did some research and found some shared superclasses:
GenericDeclaration
AnnotatedElement
Since I need both Class[] and Method[] arrays I am thinking something
like generics, so the method would look like:
public static <T extends GenericDecleration> T[] getT () {
}
As mentioned by dasblinkenlight this will not work since the method doesn't take any arguments and cannot check whether to retrieve Class or Method objects.
But how would I detect whether I need to call getDeclaredMethods or getDeclaredClasses?
What is the best approach on how to do this without duplicating a lot of code? I really tried to explain myself here, but if it is still unclear what I am doing please feel free to ask away!
Thank you very much in advance!
After messing around with this, I have found a solution that totally fits my needs. This is a combination of generics and #dasblinkenlight's solution, like so:
public interface DeclExtractor<T extends GenericDecleration> {
public T[] extract (Class clazz);
public Class<? extends T[]) getGenericClass ();
DeclExtractor<Method> methodExtractor = new DeclExtractor<Method>() {
#Override
public Method[] extract (Class clazz) {
return clazz.getDeclaredMethods();
}
#Override
public Class<? extends Method[]> getGenericClass () {
return Method[].class;
}
}
// Same for Class
}
Now the method which also will return the correct type so you dont have to manually cast all GenericDeclaration to your original object type. My issue was that I used a collection for it and not the correct array:
public <T> T[] getAll (final DeclExtractor<T> extractor, Class<?> clazz) {
T[] declaration = extractor.extract (clazz);
//.. The algorithm..
// Return an instance of a collection as array (I use a set in my implementation)
final Object[] objects = myCollection.toArray();
return Arrays.copyOf(objects, objects.length, extractor.getGenericClass());
}
Technically you do not need the getGenericClass method in the interface, but I am using extract directly in a loop so I cannot pull the class of that, however, you can.
Hopefully this helps someone in the future :) Thanks again to #dasblinkenlight for the inspiration!
Your getT needs to get some input in order to decide what to do.
What about a method which can takes an enum as argument to determine whether it needs to get classes or methods? (from a comment)
There is a better approach: define an interface that performs the appropriate extraction, and make two instances of it - one for extracting classes, and one for extracting methods:
public interface DeclExtractor {
GenericDecleration[] extract(Class cl);
final DeclExtractor forClasses = new DeclExtractor() {
public GenericDecleration[] extract(Class cl) {
// make an array of GenericDecleration from extracted classes
}
};
final DeclExtractor forMethods = new DeclExtractor() {
public GenericDecleration[] extract(Class cl) {
// make an array of GenericDecleration from extracted methods
}
};
}
Now you can rewrite your getT to take an "extractor", like this:
public static GenericDecleration[] getT (DeclExtractor extractor, Class cl) {
...
// When it's time to get components of the class, make this call:
GenericDecleration[] components = extractor.extract(cl);
...
}
To initiate a call to getT, pass DeclExtractor.forClasses or DeclExtractor.forMethods:
GenericDecleration[] c = getT(DeclExtractor.forClasses);
GenericDecleration[] m = getT(DeclExtractor.forMethods);

Why does Java call the overridden method even when object is upcasted?

I have the following classes :
public abstract class Animal
{
private String species;
public Animal(String ll)
{
species = ll;
}
public abstract void speak();
public String toString()
{
return "Species: " + species;
}
}
The 2nd class:
public class Raven extends Animal
{
String name;
public Raven(String emri)
{
super("Raven");
name = emri;
}
public void speak()
{
System.out.println("krra krra");
}
public String toString()
{
return super.toString() + "\nName : "+ name ;
}
}
and the test class :
public class TestAnimals
{
public static void main(String args[])
{
Raven blabla = new Raven("Ziosh");
Animal a = blabla;
System.out.println(a.toString());
}
}
When I execute the test class, I get :
Species: Raven
Name: Ziosh
What I don't understand is why does Java use the "new" toString() method, even after we "upcast" the Raven object to Animal ?
Thanks.
Because that's what polymorphism is all about: you can call a method of an object without knowing the actual concrete type of the object, and the appropriate method, defined in this concrete type, will be called.
This works exactly like real objects: if I give you a car, even if you don't know it's actually a hybrid car, the car will behave like a hybrid car when you drive it.
In your example, a and blabla are two references to the same object, which is a Raven instance. So this object *speak*s and *toString*s like a Raven.
When you call a method in java, even if it's cast to the super type, it always looks for the most overridden method to call.
From http://docs.oracle.com/javase/tutorial/java/IandI/override.html
The distinction between hiding a static method and overriding an instance method has important implications:
The version of the overridden instance method that gets invoked is the one in the subclass.
The version of the hidden static method that gets invoked depends on whether it is invoked from the superclass or the subclass.
Raven blabla = new Raven("Ziosh");
Animal a = blabla;
Here, a and blabla reference the exact same object, as you can confirm with:
System.out.println(a == blabla);
// prints "true"
As such, a is really a Raven, so naturally it will talk like a Raven, even if you label it an Animal.
Consider another explanation in human terms. Letting the implementation to be executed on an object of a subclass could be actually very dangerous. Imagine a Bicycle class, and its more specialized BicycleWithLittleWheels. The thing about the latter, the little wheels are quite fragile, and if you try to ride it too fast, they could break. If you let somebody ride that bicycle as if was a regular bicycle, completely obvious of the little wheels, he may break it. By similar logic, you probably shouldn't use a high-precision dental drill the same way as a sledgehammer.
This is why, intuitively, you shouldn't let a specialized object be treated as its more general form. Sure, in some cases, it may make sense to use a specialized object as if it was something more general, but not always. How could the compiler distinguish the safe cases from the unsafe cases? That would be too difficult. So to stay on the safe side, the language won't let you do this.
Java always uses the method of the instance as describe in this post:
java override method invocation

Why is it preferable to call a static method statically from within an instance of the method's class?

If I create an instance of a class in Java, why is it preferable to call a static method of that same class statically, rather than using this.method()?
I get a warning from Eclipse when I try to call static method staticMethod() from within the custom class's constructor via this.staticMethod().
public MyClass() { this.staticMethod(); }
vs
public MyClass() { MyClass.staticMethod(); }
Can anyone explain why this is a bad thing to do? It seems to me like the compiler should already have allocated an instance of the object, so statically allocating memory would be unneeded overhead.
EDIT:
The gist of what I'm hearing is that this is bad practice mainly because of readability, and understandably so. What I was really trying to ask (albeit not very clearly) was what differences there are at 'compilation', if any, between calling MyClass.staticMethod() or this.staticMethod().
Static methods are not tied to an instance of the class, so it makes less sense to call it from a this than to call it from Class.staticMethod(), much more readable too.
MyClass.staticMethod() makes it clear that you are calling a static (non-overrideable) method.
this.staticMethod() misleads the reader into thinking that it is an instance method.
staticMethod() is also on the misleading side (though I normally do it that way).
If you think of people reading your code as unfamiliar with it you tend to try to make the code clearer, and this is a case where the code is clearer by having ClassName.method instead of instance.method.
In addition to the other answers which have mentioned making it clear you're using a static method, also note that static methods are not polymorphic, so being explicit with the class name can remove any confusion as to which method is going to be called.
In the code below, it's not entirely obvious that b.test() is going to return "A" if you're expecting the polymorphism of a non-static method:
public class TestStaticOverride
{
public static void main( String[] args )
{
A b = new B();
System.out.println( "Calling b.test(): " + b.test() );
}
private static class A
{
public static String test() { return "A"; }
}
private static class B extends A
{
public static String test() { return "B"; }
}
}
If you change the code to B b = new B(); it will print out "B".
(Whether it's ever a good idea to "override" static methods is probably a discussion for another day...)
Static methods are really not part of your instance - and it will not be able to access any of your instance variables anyway, so I would dare thinking it doesn't make a lot of sense calling it from the constructor.
If your need to initialize static objects use
private static List l = new ArrayList(); static { l.add("something"); }
If you still need to call it its perfectly legal to call local static methods without prefixing your local class name, like this (no eclipse warning)
public MyClass() { staticMethod(); }
Because this. normally reference to instance methods, therefore, it's a bad idea to do that.

Overriding or overloading?

Guys I know this question is silly but just to make sure:
Having in my class method:
boolean equals(Document d)
{
//do something
}
I'm overloading this method nor overriding right? I know that this or similiar question will be on upcoming egzam and would be stupid to not get points for such a simple mistake;
Based on the code provided, we can't tell for sure whether you're overloading or overriding it.
You are most likely overloading the equals(Object o) method.
class A {
void method() {..}
}
class B extends A {
// this is overriding
void method() {..}
}
And
// this is overloading
class A {
void method(boolean b) {..}
void method(String arg) {..}
void method(int arg) {..}
}
P.S. you are using a bracket convention that is not widely accepted on the java world. In Java it is more common to place opening the curly bracket on the same.
You are not even overloading, since the other method is called equals. But if you add that s, you will be overloading equals. Although, to be precise, we talk about overloading if two (or more) methods with the same name but different signature are defined in the same class. In your case, it is trickier, since your equals with its different signature partly hides the original equals. Which is usually a bad thing, because this almost always leads to hard to understand behaviour, thus subtle bugs. Whenever someone calls equals on an instance of your class, depending on the parameter type the call may go to a different implementation of the method.
class Document {
public boolean equals(Document d)
{
//do something
}
}
Document doc1 = new Document();
Document doc2 = new Document();
String string = new String();
doc1.equals(doc2); // calls Document.equals
doc1.equals(string); // calls Object.equals!
You would be overriding Object.equals if you defined your method with the exact same signature as the original, i.e.
public boolean equals(Object obj) ...
In this case, both of the above calls to equals correctly execute Document.equals.
From the code you posted it could be either. If equal is defined in a superclass with the same parameter declarations then you are overriding it. If there is already a method called equal, but with different parameter types, you are overloading it.
On a related note, if you are using Java 5 and above and your intent is to override then it is highly recommended to use the #Override annotation before the method definition to indicate your intention. The wrong usage of this annotation (i.e. when you want to override and are not doing so) would flag a compile error.
As of Java 6 you can use the #Override annotation while defining methods that are
declared in an interface the class in implementing.
Overloading: same method name, same parameter list, different classes
Overriding: same method name, different parameter list, same or different classes.
Class A {
bool Equals(Document d) {...}
bool Equals(A a) {...} // overloaded method
}
Class B extends A {
bool Equals(Document d) {...} // overridden method
bool Equals(B b) {...} // overloaded method
}
One thing to note, the return type does not matter, it's the name of the method and the parameter list that make all the difference.

Categories

Resources