I'm confused about what it means to cast objects in Java.
Say you have...
Superclass variable = new Subclass object();
(Superclass variable).method();
What is happening here? Does the variable type change, or is it the object within the variable that changes? Very confused.
Have a look at this sample:
public class A {
//statements
}
public class B extends A {
public void foo() { }
}
A a=new B();
//To execute **foo()** method.
((B)a).foo();
Say you have a superclass Fruit and the subclass Banana and you have a method addBananaToBasket()
The method will not accept grapes for example so you want to make sure that you're adding a banana to the basket.
So:
Fruit myFruit = new Banana();
((Banana)myFruit).addBananaToBasket(); ⇐ This is called casting
The example you are referring to is called Upcasting in java.
It creates a subclass object with a super class variable pointing to it.
The variable does not change, it is still the variable of the super class but it is pointing to the object of subclass.
For example lets say you have two classes Machine and Camera ; Camera is a subclass of Machine
class Machine{
public void start(){
System.out.println("Machine Started");
}
}
class Camera extends Machine{
public void start(){
System.out.println("Camera Started");
}
public void snap(){
System.out.println("Photo taken");
}
}
Machine machine1 = new Camera();
machine1.start();
If you execute the above statements it will create an instance of Camera class with a reference of Machine class pointing to it.So, now the output will be "Camera Started"
The variable is still a reference of Machine class. If you attempt machine1.snap(); the code will not compile
The takeaway here is all Cameras are Machines since Camera is a subclass of Machine but all Machines are not Cameras. So you can create an object of subclass and point it to a super class refrence but you cannot ask the super class reference to do all the functions of a subclass object( In our example machine1.snap() wont compile). The superclass reference has access to only the functions known to the superclass (In our example machine1.start()). You can not ask a machine reference to take a snap. :)
Sometimes you will like to receive as argument a Parent reference and inside you probably want to do something specific of a child.
abstract class Animal{
public abstract void move();
}
class Shark extends Animal{
public void move(){
swim();
}
public void swim(){}
public void bite(){}
}
class Dog extends Animal{
public void move(){
run();
}
public void run(){}
public void bark(){}
}
...
void somethingSpecific(Animal animal){
// Here you don't know and may don't care which animal enters
animal.move(); // You can call parent methods but you can't call bark or bite.
if(animal instanceof Shark){
Shark shark = (Shark)animal;
shark.bite(); // Now you can call bite!
}
//doSomethingSharky(animal); // You cannot call this method.
}
...
In above's method you can pass either Shark or Dog, but what if you have something like this:
void doSomethingSharky(Shark shark){
//Here you cannot receive an Animal reference
}
That method can only be called by passing shark references
So if you have an Animal (and it is deeply a Shark) you can call it like this:
Animal animal...
doSomethingSharky((Shark) animal)
Bottom line, you can use Parent references and it is usually better when you don't care about the implementation of the parent and use casting to use the Child as an specific object, it will be exactly the same object, but your reference know it, if you don't cast it, your reference will point to the same object but cannot be sure what kind of Animal would it be, therefore will only allow you to call known methods.
Superclass variable = new subclass object(); This just creates an object of type subclass, but assigns it to the type superclass. All the subclasses' data is created etc, but the variable cannot access the subclasses data/functions. In other words, you cannot call any methods or access data specific to the subclass, you can only access the superclasses stuff.
However, you can cast Superclassvariable to the Subclass and use its methods/data.
Lets say you have Class A as superclass and Class B subclass of A.
public class A {
public void printFromA(){
System.out.println("Inside A");
}
}
public class B extends A {
public void printFromB(){
System.out.println("Inside B");
}
}
public class MainClass {
public static void main(String []args){
A a = new B();
a.printFromA(); //this can be called without typecasting
((B)a).printFromB(); //the method printFromB needs to be typecast
}
}
In this example your superclass variable is telling the subclass object to implement the method of the superclass. This is the case of the java object type casting. Here the method() function is originally the method of the superclass but the superclass variable cannot access the other methods of the subclass object that are not present in the superclass.
For example you have Animal superclass and Cat subclass.Say your subclass has speak(); method.
class Animal{
public void walk(){
}
}
class Cat extends Animal{
#Override
public void walk(){
}
public void speak(){
}
public void main(String args[]){
Animal a=new Cat();
//a.speak(); Compile Error
// If you use speak method for "a" reference variable you should downcast. Like this:
((Cat)a).speak();
}
}
in some cases we can’t provide guarantee for the type of elements or objects present inside our collection or wise,
at the time of retrieval compulsory we should perform type casting otherwise we will get compile time error.
Arrays are always type safe that is we can provide the guarantee for the type of elements present inside array.
to achieve type safety we have to use typecasting.
Casting is necessary to tell that you are calling a child and not a parent method. So it's ever downward. However if the method is already defined in the parent class and overriden in the child class, you don't any cast. Here an example:
class Parent{
void method(){ System.out.print("this is the parent"); }
}
class Child extends Parent{
#override
void method(){ System.out.print("this is the child"); }
}
...
Parent o = new Child();
o.method();
((Child)o).method();
The two method call will both print : "this is the child".
Related
abstract class Base{
protected abstract void a();
}
class Child extends Base{
#Override
public void a(){
//why is this valid
}
}
Why is that we can't reduce the visibility but can increase it?
Also I need to implement Template pattern in which the public methods visible can only be of base class.
Example:
abstract class Base{
public void callA(){
//do some important stuff
a();
}
protected abstract void a();
}
class Child extends Base{
#Override
public void a(){
//why is this valid
}
}
Now if java allows to increase visibility then there are two methods visible publicly??
I know interface is one solution but is there some other way out???
Why decreasing visibility is not allowed is already explained in other responses (it would break the contract of the parent class).
But why it is allowed to increase the visibility of a method? First, it would not break any contract, so there is no reason to not allow it. It can be handy sometimes, when it makes sense in the child class for a method to not be protected.
Second, not allowing it could have the side effect of making impossible sometimes to extend a class and implement an interface at the same time:
interface Interface1 {
public void method();
}
public class Parent {
protected abstract void method();
}
public class Child extends Parent implements Interface1 {
#Override
public void method() {
}
//This would be impossible if the visibility of method() in class Parent could not be increased.
}
About your second question, you can do nothing about it. You have to trust that the person who implements the child class doesn't do anything that breaks your implementation. Even if java wouldn't allow to increase visibility, that would still not fix your problem, because a public method with a different name could be created that calls the abstract method:
class Child extends Base{
#Override
protected void a(){
}
public void a2() {
a(); //This would have the same problems that allowing to increase the visibility.
}
}
If the base class makes a promise regarding visibility, then the subclass cannot break that promise and still satisfy the Liskov substitution principle. You can't use a subclass in any situation where the promised method is exposed if that promise is broken.
The subclass IS-A base class. If the base class exposes a method, so must the subclass.
There's no way out in Java or C++. I'd guess the same is true in C#.
Why is that we can't reduce the visibility but can increase it?
Suppose that it would be possible to reduce the visibility. Then look at the following code:
class Super {
public void method() {
// ...
}
}
class Sub extends Super {
#Override
protected void method() {
// ...
}
}
Suppose that you would have another class, in another package, where you use these classes:
Super a = new Sub();
// Should this be allowed or not?
a.method();
To check whether a method call is allowed or not, the compiler looks at the type of the variable you call it on. The type of the variable a is Super. But the actual object that a refers to is a Sub, and there the method is protected, so you would say it should not be allowed to call the method from an unrelated class outside the package. To solve this strange situation, it's made forbidden to make overridden methods less visible.
Note that the other way around (making a method more visible) doesn't lead to the same problem.
Since Java allows Super class reference to point to sub class object.. So, restriction should not be increased from compile-time to runtime..
Lets see this through an example: -
public class B {
public void meth() {
}
}
class A extends B {
private void meth() { // Decrease visibility.
}
}
Now, you create an object of class A and assign it the reference of class B..
Lets see how: -
B obj = new A(); // Perfectly valid.
obj.meth(); // Compiler only checks the reference class..
// Since meth() method is public in class B, Compiler allows this..
// But at runtime JVM - Crashes..
Now, since compiler only checks the type of the reference variable, and check the visibility of methods in that class (class B), and it doesn't check what kind of object does the reference obj refers to.. So, it is not worried about that.. It is left to JVM at runtime to resolve the appropriate method..
But at runtime, JVM will actually try to invoke the meth method of class A as object is of class A.. But, now what happens... BooooOOMM ---> JVM Crashes.. because meth method is private in class A...
That's why visibility is not allowed to be decreased..
class Bank{
float getRateOfInterest(){return 0;}
}
class SBI extends Bank{
float getRateOfInterest(){return 8.4f;}
}
class TestPolymorphism{
public static void main(String args[]){
Bank a = new SBI();
SBI b = new SBI();
a.getRateOfInterest();
b.getRateOfInterest();
}
}
a.getRateOfInterest() and b.getRateOfInterest() both gives same output. So what is the difference between both the statements?
I think 1st is upcasting.
Java methods are all virtual, so the method called depends on the run-time type of the called object, not on the compile-time type of the variable holding the reference.
It's not, if you construct it with new SBI(). It'll always return 8.4f.
All java method is virtual (by design).
They rely on the implementing classes to provide the method implementations.
Here is more information.
- Can you write virtual functions / methods in Java?
- https://en.wikipedia.org/wiki/Virtual_function
Here is an excerpt from wikipedia :-
public class Animal {
public void eat() {
System.out.println("I eat like a generic Animal.");
}
public static void main(String[] args) {
Animal animal=new Wolf ();
animal.eat(); //print "I eat like a wolf!
}
}
class Wolf extends Animal {
#Override
public void eat() {
System.out.println("I eat like a wolf!");
}
}
Virtual functions are resolved 'late'. If the function in question is
'virtual' in the base class, the most-derived class's implementation
of the function is called according to the actual type of the object
referred to, regardless of the declared type of the pointer or
reference. If it is not 'virtual', the method is resolved 'early' and
the function called is selected according to the declared type of the
pointer or reference.
Virtual functions allow a program to call methods that don't
necessarily even exist at the moment the code is compiled.
When a class extends a class, we can use Super-class reference while assigning memory to the subclass object.
I have understood so far is that it is ok to do so, because a subclass inherits the data of its parent class, but it cannot access the members of the subclass because it is the just the reference, and hence does not know of what additions are done by the child class.
My question is when I included method hiding to the above concept, the superclass reference variable started to refer to the child's class function. Why is that ? Why it didnt call it's own method as it is supposed to ?
class A{
void show(){ System.out.print("CLass A. \n"); }
}
class B extends A{
void show(){System.out.print("Class B. \n"); }
}
class Main{
public static void main(String[] args){
A a= new A();
B b= new B();
a.show(); // prints Class A
b.show(); // prints Class B
A a1= new B();
a1.show(); // print Class B. why is this ? it should be Class A as per theory?
}
}
variables and methods are two different things. Variables stick to their types where as methods get executed run time based on the implementation type provided.
Polymorphism. Methods bind dynamically and choosen at run time. If you ovveride them implementation class, they get executed otherwise the implementation from type class gets execute.
When you write
A a1= new B();
Means that please call the implementations from the class B(which is on right side) which are from type A
You have to know about overriding concept in java.
From oracle documentation page regarding overriding:
Overriding and Hiding Methods
Instance Methods
An instance method in a subclass with the same signature (name, plus the number and the type of its parameters) and return type as an instance method in the superclass overrides the superclass's method
The ability of a subclass to override a method allows a class to inherit from a superclass whose behavior is "close enough" and then to modify behavior as needed.
But overriding is different from hiding.
Static Methods
If a subclass defines a static method with the same signature as a static method in the superclass, then the method in the subclass hides the one in the superclass.
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.
Example to understand:
public class Animal {
public static void testClassMethod() {
System.out.println("The static method in Animal");
}
public void testInstanceMethod() {
System.out.println("The instance method in Animal");
}
}
public class Cat extends Animal {
public static void testClassMethod() {
System.out.println("The static method in Cat");
}
public void testInstanceMethod() {
System.out.println("The instance method in Cat");
}
public static void main(String[] args) {
Cat myCat = new Cat();
Animal myAnimal = myCat;
Animal.testClassMethod();
myAnimal.testInstanceMethod();
}
}
output:
The static method in Animal
The instance method in Cat
It allways calls the method from the most specific class.
I am a newbie in Java, and would like to understand more about inheritance. Suppose
class Vehicle{
public void move(){
System.out.println(“Vehicles can move”);
}
}
class MotorBike extends Vehicle{
public void move(){
System.out.println(“MotorBike can move and accelerate tool”);
}
}
class Test{
public static void main(String[] args){
Vehicle vh=new MotorBike();
vh.move();
vh=new Vehicle();
vh.move();
}
}
When we do vh.move() in the 1st time it prints MotorBike can move and accelerate tool. Second time it prints Vehicles can move.
It can be called method overriding. Because we have same method name in two class.
But, if two classes have different method, then which method should be called? I want to say like that,
class Vehicle{
public void move(){
System.out.println(“Vehicles can move”);
}
}
class MotorBike extends Vehicle{
public void part(){
System.out.println(“MotorBike can move and accelerate tool”);
}
}
class Test{
public static void main(String[] args){
vehicle a = new vehicle();
Vehicle vh=new MotorBike();
}
}
In the first case vehicle a = new vehicle();it invoke move() and
What will be the second case? If I do `Vehicle vh=new MotorBike();
Which method should be called? move() or part()?
In the second case, even though you have defined an extra method part(), you can only call the move() method (which is inherited from Vehicle) because you have told the compiler that vh is a Vehicle (it doesn't know that it's a Motorbike)
Vehicle vh = new MotorBike(); // from now on, vh is a Vehicle - we don't know it's a MotorBike
vh.move(); // this is fine
vh.part(); // this will not compile
If you want to call the part() method then you have to define the variable as a MotorBike:
MotorBike vh = new MotorBike(); // now we know it's a MotorBike
vh.part(); // this is ok now
it can be called method overridding.becoz we have same method name in
two class.
Well, yes ... but what your code illustrates is that the same method invoked on two objects referenced by the same variable can exhibit different behavior (that is determined by their underlying type). Yes, this requires overloading, but the principle that has been demonstrated is polymorphism.
what will be the 2nd case?if i do Vehicle vh=new MotorBike(); which
method should be called? move() or part()??
In polymorphism, the most specific method in an object hierarchy gets invoked when that method is invoked on an object reference. Consider this example:
public class Parent {
public void emote() {
System.out.println("I'm the parent")'
}
public void parentMethod() { ... }
}
public class Child extends Parent {
#Override
public void emote() {
System.out.println("I'm the child");
}
public void childMethod() { ... }
}
Now consider the following test code:
public void test() {
Parent p1 = new Parent();
p1.emote(); // method invocation prints "I'm the parent"
Parent p2 = new Child();
p2.emote(); // prints "I'm the child"
}
Note that the p2 variable type does not determine the method that gets invoked when the emote() method is called. This is important to understant because a reference variable can point to an object of its own type ... or to any other object that is a subclass of the variable's type.
The method that is invoked is the most specific method that applies to the actual object that is referenced by the variable. In this case, the emote() method on the Child object itself is invoked.
Also, this is valid:
p2.parentMethod();
Even though p2 references a Child object, the Child class inherits the parentMethod() method from it and so the invocation works. These fail, though:
p1.childMethod();
p2.childMethod();
The Parent class does not know anything about the methods that any of its subclasses may define. It may not be intuitive why the second invocation should fail. Although p2 references a Child object, the Parent class does not have a childMethod() declaration. To make this work, we would need to cast p2 to the Child type:
((Child) p2).childMethod();
I tried with below example, it is working fine.
I expected it to pick sub-class's value since object won't be created for super class (as it is abstract). But it is picking up super class's field value only.
Please help me understand what is the concepts behind this?
abstract class SuperAbstract {
private int a = 2;
public void funA() {
System.out.println("In SuperAbstract: this.a " + a);
}
}
class SubClass extends SuperAbstract {
private int a = 34;
}
I am calling new SubClass.funA();
I am expecting it to print 34, but it is printing 2.
P.S.:
What I want to know is why using this in an abstract class not giving me an error?
As below text is emphasizing this would work on an instance and abstract classes won't have an instance.
Within an instance method or a
constructor, this is a reference to
the current object — the object whose
method or constructor is being called.
You can refer to any member of the
current object from within an instance
method or a constructor by using this.
from: http://java.sun.com/docs/books/tutorial/java/javaOO/thiskey.html
To answer the question in the title: Yes, this can be used in an abstract class. An abstract Animal is created at the same time as a Dog is created.
Overriding fields
You can't override fields the way you have tried it. Fields "are not virtual" like methods.
From Java Quick Reference: Overloading, Overriding, Runtime Types and Object Orientation - Overriding Methods
fields cannot be overridden but they can be hidden ie if you declare a field in a subclass with the same name as one in the superclass, the superclass field can only be accessed using super or the superclasses type
If you could, the field would probably have had to be at least protected :-)
Creation of objects of abstract classes
since object won't be created for super class (as it is abstract)
It is actually instantiated.
The abstract keyword only ensures that, when instantiated, it's instantiated in the form of a subclass. When instantiating a Dog, you're at the same time instantiating an Animal! The this reference in the context of an Animal will thus always refer to a Dog or a Cat or whatever, but in all cases it refers to some Animal. :-)
As the example below illustrates, the this reference makes sense even in an abstract class:
abstract class Animal {
public String name;
public Animal(String name) {
System.out.println("Constructing an Animal");
this.name = name;
}
public abstract void speak();
}
class Dog extends Animal {
public Dog(String name) {
super(name);
System.out.println(" Constructing a Dog");
}
public void speak() {
System.out.println("Bark! My name is " + name);
}
}
public class Test {
public static void main(String... args) {
new Dog("Woffy").speak();
}
}
Prints:
Constructing an Animal
Constructing a Dog
Bark! My name is Woffy
Update: The this reference refers to the same object in the super class as in the sub class.
You could try to add
public Animal getSuperThis() { return this; }
to the animal class, and do
System.out.println(this == getSuperThis());
in Dog.speak(). You would see that it prints true.
Any field declared in a class is unique, even if it has the same name as a a field in a base class (i.e. only methods can be overridden, but not fields). Therefore, there are two distinct fields in the derived class: SuperAbstract.a and SubClass.a. The fact that the base class is abstract has no impact.
The abstract keyword simply signifies that a class cannot be instantiated, i.e. you cannot write new SuperAbstract(). You can only instantiate object of the subclass, which must override all methods marked abstract.
The code you provided contains variable a as private member of the SuperAbstract class. Since, you don't seem to override the function, it represents the code from the SuperAbstract class, and executing it will get access to the a declared in the class itself, regardless of the fact that it is being called from any inherited class. To access the value of the later variable, you need to override the function by defining the function again in the derived class. The final code looks like this:
abstract class SuperAbstract {
protected int a = 2;
public void funA() {
System.out.println("In SuperAbstract:" + this.a);
}
}
class SubClass extends SuperAbstract {
private int a = 34;
//Overriding the above function
public void funA() {
System.out.println("In SubClass: " + a);
//Or even check using the super keyword
System.out.println("In SubClass with super: " + super.a);
//Now call the function to display the value of a from SuperAbstract
super.funA();
}
}
In the above code I changed the a to protected, so that it could be accessed from the derived class too.