Java: Casting and Inheritance - java

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.");
}
}

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();
}
}

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).

Related

Using method that return MyClass object within MyClass when MySubClass extends MyClass

I have trouble subclassing a very simple class that has methods returning the initial class too.
public class MyClass {
public MyClass(){
}
public MyClass filterOn(String something){
MyClass result=new MyClass();
result.doSomethingUsingThisInstance(this, something);
return result;
}
}
public class MySubClass extends MyClass{
....
}
Ok, now if I want to call this:
MySubClass subClass=new MySubClass();
MySubClass subClass2=(MySubClass)subClass.filterOn("Hello World");
Then I have a java.lang.ClassCastException:cannot cast MyClass to MySubClass
How to prevent this?
Override the filterOn() method to create the instance you wish in MySubClass :
public class MySubClass extends MyClass{
public MyClass filterOn(String something){
MySubClass result = new MySubClass();
result.doSomethingUsingThisInstance(this, something);
return result;
}
....
}
You could also avoid duplication in filterOn() method by introducing a method in MyClass to create a instance of the current class that we override in subclass:
public class MyClass {
public MyClass(){
}
public MyClass createSpecificInstance() {
return new MyClass();
}
public MyClass filterOn(String something){
MyClass result = createSpecificInstance();
result.doSomethingUsingThisInstance(this, something);
return result;
}
}
Now Sub class only override createSpecificInstance() :
public class MySubClass extends MyClass {
public MyClass createSpecificInstance() {
return new MySubClass();
}
}
(MySubClass)subClass.filterOn("Hello World");
and
public MyClass filterOn(String something)
You can not cast base class to derived class. if you do, you'll get that exception, ClassCastException
Read this: java.lang.ClassCastException
You try to cast your return value to a derived type, which does not work and results in the class cast exception.
Reason: Casting upwards in the type hierarchy works, since your base class requires only attributes/ methods the derived class (trivially) has. The other way around does not work since it may result in problems. Consider:
class Base {
// some stuff here
}
class Derived1 extends Base {
private int foo;
}
class Derived2 extends Base {
private String bar;
}
Base myObject = new Derived1();
// this works, Derived1 has everything Base requires
// myObject.foo still exists, but can not be trivially accessed.
Derived2 myOtherObject = (Derived2)myObject;
// Now what?
// What happens to myObject.foo?
// Where does myOtherObject.bar come from?
What can you do in your situation:
If the implementations of filterOn() are very different depending on the concrete implementation of the derived class, make it abstract in the base class and re-implement it in the derived class.
Check if you have a design problem. Do you really need to cast the result of filterOn() to the derived class?
Use Generics. Remember you can use a derived class as generic in a base class. This only works if the implementation of filterOn() is exactly the same for each subclass (except the types of course).
Provide a constructor that allows creating a derived class instance from the base class. Use it instead of the cast. Something in the line of
Derived1(Base baseObject){
// copy all the stuff from the base object
this.foo = 0; // initialize the rest
}
Maybe inheritance is not what you need. Composition has the tendency to beat inheritance a lot (Explained nicely here). So you can try that:
class BetterThenDerived {
private Base myBaseObject;
private int foo;
}
This is a side of the problem of covariance. See for example Covariance and contravariance. And Demonstrate covariance and contravariance in Java?. It’s not really where Java excels, but there are a couple of options.
First, when overriding a method, you are allowed to declare a more specific return type. For example, in MySubClass you may declare:
#Override
public MySubClass filterOn(String something) {
// ...
}
Now this doesn’t solve your problem. You still need a way for this method to create and do something to a MySubClass object. What it does do, it frees the client code from needing a cast at all. You may take the implementation of the method form davidxxx’s answer (provided that result.doSomethingUsingThisInstance() is protected or public):
#Override
public MySubClass filterOn(String something) {
MySubClass result = new MySubClass();
result.doSomethingUsingThisInstance(this, something);
return result;
}
You may be annoyed to have to duplicate this method in all you subclasses. If the real work stays in result.doSomethingUsingThisInstance() I should think you may be able to live with it.
The other idea is to clone() for producing an object of the correct runtime type:
public class MyClass implements Cloneable {
public MyClass filterOn(String something) {
try {
MyClass result = (MyClass) this.clone();
result.doSomethingUsingThisInstance(this, something);
return result;
} catch (CloneNotSupportedException cnse) {
throw new AssertionError(cnse);
}
}
}
I’d think twice before using this idea, though. One reason your clone contains data that you don’t want to be in there, so you may have to make sure it’s cleared before working on the clone. You may still combine it with returning the specific subtype in the subclass, now it just requires a cast (still inside the implementation, nothing the client needs to worry about):
public class MySubClass extends MyClass {
#Override
public MySubClass filterOn(String something) {
return (MySubClass) super.filterOn(something);
}
}

Is it possible to acces this.getClass() before calling super()

I want to call this.getClass() before calling the constructor with super(...).
abstract class A extends SuperClass {
public A() {
super(Manager.someOtherMethod(this.getClass()))
// Does not work: "Cannot reference 'Object.getClass()' before
// supertype constructor has been called".
}
}
I read about a workaround using static methods, but this.getClass() cannot be called from a static context.
This question depends on my previous question.
Thanks in advance for you answers :)
Whilst I am dubious about the need for this, you can do it by inserting the call to Manager.someOtherMethod into the constructor of the superclass:
class SuperClass {
SuperClass() {
Object result = Manager.someOtherMethod(this.getClass());
}
}
class A extends SuperClass {}
class Manager {
static Object someOtherMethod(Class<?> clazz) {
System.out.println(clazz);
return new Object();
}
}
would print out
class A
(if you create an instance of A)
Ideone demo
If SuperClass has multiple constructors, you can assign the result to a field in the superclass:
class SuperClass {
private final Object result = Manager.someOtherMethod(this.getClass());
SuperClass() { ... }
SuperClass(String someParameter) { ... }
}
then result will be available in both constructors.
I suggest you to refactor your code.
I assume that you have classes A1, A2 and A3 now.
You should introduce factory like this:
class AFactory {
public static A1 newA1() {return new A1(A1.class);}
public static A2 newA2() {return new A2(A2.class);}
public static A3 newA3() {return new A3(A3.class);}
}
Add parameter to classes A1, A2 and A3 constructors.
Add parameter to A constructor.
...what's the question? Do I understood correctly, do you want the class to be subclassed, and THAT class should be given to the super, but you don't want to call super in all the subclasses?
Indeed it can't be done this way as the class object is not constructed yet, and therefore it does not exist. So you cannot call a method on the object yet, or ask for the name, or whatsoever.
I think you're stuck with either a class passing on to super, or add a pretty useless public static class<? extends SuperClass> getThisClass() { ... } or am I missing something nice? if I do, pls comment, as I actually like to know myself too.
Just for curiousity I tried different ways which are stated here: Getting the class name from a static method in Java but the closest I got was getting that class test.staticgetclass.A in the middle class, but never its subclass name which I think you want to get.
Use a class literal as a constructor parameter
abstract class A extends SuperClass {
protected A(Class<? extends A> clazz) {
super(Manager.someOtherMethod(clazz));
}
Then in impl:
class B extends A {
public B() {
super(B.class);
}

Accessing Subclass Methods and Instances From Within a Method With A Superclass Parameter

Novice Java programmer here...
So I have this superclass:
public abstract class Animal
{
public abstract String attack(Animal entity);
}
and then I have this subclass:
public class Dog extends Animal
{
protected int something;
public int getSomething()
{
return something;
}
#Override
public String attack(Animal entity)
{
entity.getSomething();
//THIS RIGHT HERE
}
I'm not asking why this isn't working as much as I'm asking how I would go about accessing those methods and instances within that subclass. Should I create a new instance of Dog within the attack method and assign entity to the newly created instance? What is the "right" way to go about accomplishing this?
What you are trying to do is to invoke the method getSomething() on an instance of class Animal in your implementation of the attack(Animal entity) method.
This clearly can't work, because this method is not defined for class Animal. I believe you want that the dog can attack any type of animal and vice versa. What you have to do then is to add the method to the Animal:
public abstract class Animal {
public abstract String getSomething();
//rest
}
Then you clearly have to override the method in every subclass of animal. Or, if possible in your use case, at the attribute to the animal class and implement the getSomething() method directly there:
public abstract class Animal {
private String something;
public String getSomething() {
return this.something;
}
//rest
}
Please think again about the visibility protected of your attribute. If something is protected, than every instance of classes in the same package can access and modify it without the getter.
Dog has an is-a relationship with Animal. This does not go vice versa. Therefore a custom method defined in dog cannot be used in its parent class unless it is an overridden method

How do I enforce a child class from an abstract class to implement a static method

I have the abstract class Animal, and then I have classes like Dog and Cat, wich extend the class Animal.
I would like to make sure that all child classes of the parent class Animal have a static method: getProperties. Even when someone else, who doesn't have access to my code, implements a new Animal child class.
I want it to be static since all Animals of class Dog have the exact same properties (or you don't need a Dog to know how a Dog looks like genericly), and therefor it makes sense that it's a method called on the classtype, rather then a class instance.
Is this possible?
A static in Java means that the method (for example) in not related to any of the instances of the class. It's common to all the instances and it's implementation is just nested within the class.
As I read you problem, I believe you need an abstract method in the Animal class.
public abstract class Animal {
public abstract <some-return-type> getProperties();
}
In this case, every class which inherits Animal will have to provide an implementation of the getProperties method (which is not static in this case).
If you want it to be static, just make it so (within the Animal class), but then you will have a single and shared implementation.
The Java Object model doesn't support class-side inheritance (unlike Smalltalk or Ruby).
You have to explicitly implement a meta model of your domain, for instance, like this:
public abstract class AnimalDescriptor<T> { // or <T extends Animal>
public abstract List<String> getProperties();
public abstract T newAnimal();
}
public class DogDescriptor extends AnimalDescriptor<Dog> {
public static final DogDescriptor INSTANCE = new DogDescriptor();
public List<String> getProperties() { ... }
public Dog newAnimal() { return new Dog(); }
}
void doStuff(AnimalDescriptor<?> desc) {
desc.getProperties();
}
doStuff(DogDescriptor.INSTANCE);
This is just an example, you will have to adapt it to suit your needs. For instance, you might want to add a getDescriptor() method on the animal side.
No, not possible. There's no inheritance in static contexts. And no, there's no way to enforce a class to implement a static method.
That's not possible in Java, at much you could "hide" a static method, but not "override" it.
If you want to have each Animal class provide metadata about it, give it instance methods like getProperties, getNumberOfLegs, getLocomotionType, etc. You can implement these using static constants:
public abstract class Animal {
public abstract int getNumberOfLegs();
}
public class Dog {
private static final NUMBER_OF_LEGS = 4;
public int getNumberOfLegs() {
return NUMBER_OF_LEGS;
}
// ...
}
I suppose you wanted a Map of some sort for the getProperties method. The problem with that is that you must be very careful to make the map you return immutable. One mistake, and someone can change the static instance for everyone. making the method an instance method costs you almost nothing.
Static methods need to be able to run without you explicitly creating a new instance of the Animal class. You will have to fully implement Animal.getProperties().

Overriding a method

public class Testing extends JDialog {
public MyClass myClass;
public Testing() {
}
}
given the above code, is it possible to override a method in myClass in Testing class?
say myClass has a method named computeCode(), will it be possible for me to override it's implementations in Testing? sorry it's been a long time since I've coded.
if you want to override a method from MyClass then your testing class must extend that. for overriding a method one must complete IS-A relationship whereas your code comes under HAS-A relationship.
Yes, it is generally possible (note that as others have correctly mentioned - you'd need to extend it to override the method). Refer to this sample:
public class Animal {
public void testInstanceMethod() {
System.out.println("The instance method in Animal.");
}
}
public class Cat extends Animal {
public void testInstanceMethod() {
System.out.println("The instance method in Cat.");
}
public static void main(String[] args) {
Cat myCat = new Cat();
Animal myAnimal = myCat;
myAnimal.testInstanceMethod();
}
}
Not only is it possible, but it is a key feature in polymorphism an code reusability.
Note, however, that MyClass.computeCode might be final - in this case, it cannot be overridden.
You override methods of classes that you extend. Therefore, in your example your Testing class could override the various existing methods of JDialog. If you wanted to override computeCode() from MyClass (assuming it's not final), you should make Testing extend MyClass.
public class Testing extends MyClass
{
#Override
public int computeCode()
{
return 1;
}
}
You can override a class's method only in a subclass (a class that extends the class whose method you want to override). However, given your skeletal code, you can (within Testing) have a nested class that extends MyClass and force an instance of that nested class into the myClass instance variable... so, the answer must be "yes".
Whether that's the best choice (as opposed to using interfaces, rather than subclassing concrete classes, and relying on Dependency Injection to get the implementations most suited for your testing), that's a different question (and my answer would be, unless you're testing legacy code that you can't seriously refactor until it's well test-covered... then, probably not;-).
See, if you want to override method from MyClass then you need to extend it.
As per your code, it seems you want to make a wrapper wround MyClass.
Wrapper means, calling implemented class method will call method of MyClass.
I am just clearing how wrapping works as below.
public class Testing extends JDialog {
public MyClass myClass;
public Testing() {
}
public void someMethod() {
//Add some more logic you want...
...
..
myClass.computeCode();
}
}
thanks.
The wording of the question is confused and lost.
Here are some key points:
You can't #Override something that you didn't inherit to begin with
You can't #Override something that is final
Here's a small example:
import java.util.*;
public class OverrideExample {
public static void main(String[] args) {
List<String> list = new ArrayList<String>(
Arrays.asList("a", "b", "c")
) {
#Override public String toString() {
return "I'm a list and here are my things : " + super.toString();
}
};
System.out.println(list);
// prints "I'm a list and here are my things : [a, b, c]"
}
}
Here, we have an anonymous class that #Override the toString() method inherited from java.util.ArrayList.
Note that here, it's not class OverrideExample that overrides the ArrayList.toString(); it's the anonymous class that (implicitly) extends ArrayList that does.
All the above answers are valid. But, if you want to extend JDialog but still if you want to override a method of another class it is possible through interfaces. Interfaces won't have method definitions but will have method declarations. More about interfaces, you can read at http://java.sun.com/docs/books/tutorial/java/concepts/interface.html
In your case, you can make use of interface like this
public interface MyInterface{
public void myMethod();
}
public class Testing extends javax.swing.JDialog implements MyIterface{
public void myMethod(){
// code for your method
}
}
Since Testing class has already inherited JDialog, there is no way let it inherit MyClass again unless to implement an interface. What you can do is to use some design pattern. However this is not overriding, since there is no inheritance. The Adapter is the one you need. Again you are losing the flexibility of polymorphism.
public class Testing extends JDialog {
MyClass myClass = new MyClass();
public Testing() {
}
public void methodA(){
myClass.methodA();
}
}
class MyClass {
public void methodA(){}
}

Categories

Resources