Domanda

Okay, so recently I realized that I have some misunderstandings with extending and inheritance inside of java.

So far, my understanding states that you cannot do this

MySubClass myClass = (MySubClass) new MyClass();

That makes enough sense to me, but there are a few gabs and work-arounds that I don't know how to succeed in, such as if a person is trying to get a SubClass from a method that returns the SuperClass. For example:

public static MyClass getNewMyClass() {
    return new MyClass();
}

And inside of MySubClass there are specific methods I want to access, such as

public void sayBye() {
    System.out.println("Bye.");
}

So what I would think is I need to do is

((MySubClass) myClass).sayBye();

..but of course that throws a ClassCastException.

Summary/Question

So basically my question will be, how do I get the subclass of a returned class from a method, or is it possible?

Example: MyClass.getNewMyClass() returns a new MyClass, but I want to use the method sayBye() in its subclass, MySubClass.

More Information

The reason I'm asking this is because I'm trying to create an API for myself that basically will shorten the development of what I am trying to accomplish. In one of my classes, it contains a whole bunch of methods that returns MyClass. Some method examples could be public MyClass getNewMyClass() {}, public MyClass findMyClass(String name)() {} and so on.

But when I get to exending MyClass for some extra methods, I have about 10 methods from the superclass that returns MyClass, and all of that basically will leave me back to the beginning. Is there the possibility of returning Class<? extends MyClass> instead, or something similar?

Solved

Thank you everyone so much for your help, it is very much appreciated! So I basically decided to go with delegation. To solve my issue, here were all of my code and classes, that allowed me to access the superclass, but return the subclass.

Here was my InheritanceTest.java

public class InheritanceTest {
    public static void main(String[] args) {
        MyClass myClass = MySubClass.doMath();
        if (myClass instanceof MySubClass) {
            ((MySubClass) myClass).sayBye();
        }
    }
}

And my MyClass.java

public class MyClass {

    protected String name;

    public MyClass(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public static MyClass getNewMyClass() {
        return new MyClass("Toshimaru");
    }

    public void sayHi() {
        System.out.println("Hi.");
    }
}

And finally, where it all seems to be resolved, MySubClass.java

public class MySubClass extends MyClass {

    public MySubClass(String name) {
        super(name);
    }

    public static MySubClass doMath() {
        // Got the new instance of MyClass
        MyClass myClass = getNewMyClass();
        // And turned it into a MySubClass with myClass' properties.
        myClass = new MySubClass(myClass.getName());
        return (MySubClass) myClass;
    }

    public void sayBye() {
        System.out.println("Bye.");
    }
}
È stato utile?

Soluzione

The trouble with trying to get a subclass from a superclass is you don't know what subclass it is. You could do an instanceof check first before casting and that would avoid the ClassCastException, but that is nasty. Ideally you should have your methods return objects that are as high up the hierarchy as possible but if you need a method that belongs to a subclass then that should be the return type of the method.

EDIT:

Your more information is a little vague, but this is legal:

public class MyClass {

    public MyClass getNewMyClass(){
        return new MyClass();
    }
}

public class MySubClass extends MyClass{

    @Override
    public MySubClass getNewMyClass() {
        return new MySubClass();
    }
}

Altri suggerimenti

You can't make an Animal to bark, Only a sub class of Animal, Dog can bark.

In the same way, You can't invoke a sub class method on super class instance. Object oriented concepts are very much similar to real world.

MySubClass is an acceptable return for MyClass. I would instead return new MySubClass() which would then be able to call the subclass method. Polymorphism applies.

All Toyotas are Cars, but not all Cars are Toyotas. How does this relate here? In this example, Car is analogous to your MyClass and Toyota is analogous to your MySubClass.

If you create an object as a Car, you won't have access to the methods inside Toyota. However, if you create an object as Toyota, you do have access to the public (or protected) methods inside Car.

If you're the designer of MyClass and MySubClass, and you think sayBye() is a method that should be accessible at the parent level, then maybe you need to consider redesigning/refactoring and making sayBye() a method in your parent class.

This cast:

((MySubClass) myClass).sayBye();

does NOT always throw a ClassCastException, as you said, but it depends on what is the actual (more specific) type of the object referenced by the variable myClass.

If the variable MyClass myClass references an object of the class MySubClass, then the cast does not throw any exception.

But the point is that, if you want to call a method of an object, this method must be defined and implemented in the class (or some superclass) of that object, while you can NOT call a method on a object, where this method is only implemented in some of its subclass, because in this case that method is not present in that object (but only on object of its subclass).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top