Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use subclass methods from another subclass, lateral casting?

In Java, I was given an assignment. I could describe my issue with it generally as follows:

Create three classes A B and C.

Class A has instance variables j,k,l, setter and getter methods, and also method x which makes a calculation based on them.

Class B is a subclass of A and overrides method x with the same empty signature, using j,k,l.

Class C is also a subclass of A, and has an additional class y which does other junk.

Now, instantiate a class C object, set its variables, execute method x and then use the overriden version of method x from class B.

My question is, how do I do that last part? I think either the question is incorrect or else I am interpreting it wrong. Can I cast my class C object to a class B object and then use the class B version of x()? I don't know much about casting objects and what determines whether it is possible to cast from one thing to another. Upcasting could be just as lossy as "horizontal/lateral" casting but I have never heard of the latter. Is it impossible to use the method in class B from class C without making class C internally instantiate and rebuild a class B object from its own variables? Am I making sense?

Addendum:

Okay. So siblings cannot be cast as one another? Because C and B are both "part of [my] object hierarchy". Could I cast up and then back down to a different subclass? Like casting a cat to an animal class and then an animal to a dog? Because method x relies on instance variables in both class A AND class B, creating a new instance of B within C will create an object with fields/variables which are not set the same, they will all be zero or similar. So I will have to essentially have to copy over each value of j,k and l into the new B type object within the C class object. This seems like a waste of time and memory, copying the object variables into another very similar object. But there is no other way?

Second Addendum:

Although I have selected an answer, I am still curious about casting in general and what I call lateral-casting. If B and C are both sub-classes of A, can you allow casting from B to C? Also, how does one allow casting in general?

Third:

So at this point, a couple years later I understand that this is not really possible in Java. However, interestingly in JavaScript and PHP you can use the "bind" method of a function to change it's context so that it essentially thinks it's another object. So in this scenario I could create a copy of B:x() bound to an instance of C containing the properties I have set, the bound instance of x would then use all of the internal variable of the instance of C. It's really weird but really handy sometimes.

Here is an example of using a method from one subclass on a different subclass; making a cat speak using a dog's speak function:

class Animal {
  constructor(){
  }
}
class Dog extends Animal{
  constructor(){
    super()
    this.sound = 'bark'
  }
  speak(){
    console.log(this.sound)
  }
}
class Cat extends Animal{
  constructor(){
    super()
    this.sound = 'meow'
  }
}
var mycat = new Cat()
var mydog = new Dog()
mydog.speak()
mydog.speak.bind(mycat)()

So it's basically as if cat has the speak function. This is the sort of thing I wanted to do in Java.

like image 777
ADJenks Avatar asked Oct 18 '22 14:10

ADJenks


1 Answers

Casting means you know better than the compiler what your object is. If you cast to something that isn't part of your object hierarchy you will get an exception (specifically a ClassCastException) when you run the program.

The most common place you see casting is in the Object#equals method. equals needs to take a java.lang.Object as its only argument. If you look at how people implement equals, you'll see testing for what the class of the passed-in object is, and if it's what's expected then there's a cast so that the checks that follow can use that object's fields. Otherwise casting doesn't come up in beginner situations much.

Casting does not change what your object is, it only tries to inform the compiler what the object is in circumstances (like equals) where the type system is not sufficient. If you are creating objects with virtual methods in a hierarchy, casting does not change which version of the method gets called.

If C is not a subclass of B then you can create an object of class B within C, as an instance member or as a local variable of some method of B, and call the method of C on that, something like:

class C extends A {
    private B b; // instance member

    public C(B b) {
        this.b = b;
    }

    public void x() {
        // do stuff
        b.x();
    }
} 
like image 180
Nathan Hughes Avatar answered Oct 22 '22 18:10

Nathan Hughes