Why i cant assign my super class object to extended class? - java

Why i cant assign my super class object to base class
class Alpha {
String getType() {
return "alpha";
}
}
class Beta extends Alpha {
String getType() {
return "beta";
}
}
public class Gamma extends Beta {
String getType() {
return "gamma";
}
public static void main(String[] args) {
Gamma g1 = new Alpha();
Gamma g2 = new Beta();
System.out.println(g1.getType() + " "
+ g2.getType());
}
}
Can anyone tell me the reason why it is not possible.

You're trying to assign a child class to a parent class. Which is exactly the opposite of what you should be doing.
Imagine you've got classes:
public class Mammal {
}
public class Dog extends Mammal {
}
public class Cat extends Mammal {
}
Do you think it would be logical to assign:
Cat cat = new Mammal();
Is any Mammal a Cat?

No. A reference to a subclass must refer to an instance of itself or one of its subclasses (or null). Because it will not behave correctly.
What sense does the following program make ?
Object o = new Object();
String s = (string) o;
int i = s.length();

You can add cast to compile code:
package com.stackoverflow.main;
class Alpha {
String getType() {
return "alpha";
}
}
class Beta extends Alpha {
String getType() {
return "beta";
}
}
public class Gamma extends Beta {
String getType() {
return "gamma";
}
public static void main(String[] args) {
Gamma g1 = (Gamma) new Alpha();
Gamma g2 = (Gamma) new Beta();
System.out.println(g1.getType() + " " + g2.getType());
}
}
but it will give you exception at runtime
Exception in thread "main" java.lang.ClassCastException: com.stackoverflow.main.Alpha cannot be cast to com.stackoverflow.main.Gamma
at com.stackoverflow.main.Gamma.main(Gamma.java:21)
Because in java you can't cast instance of base type to subtype

Related

Implement a common function accepting argument of two different classes?

I have two classes A and B and they both have a common field in them, and I want to create a function in which if I pass Class A object then I want to set that common field value to the passed value and if I pass Class B object then I want to set that common field value to the passed value. Can anyone please tell me how can I do this, I am new to Java Generic Classes.
Otherwise I would have to make two different functions OR I would have to make an if and else which would decide that passed object belongs to which class ??
Class A
public class A{
int footer;
public void setFooter(int fo) {
footer = fo;
}
}
Class B
public class B{
int footer;
public void setFooter(int fo) {
footer = fo;
}
}
Class D
public class D{
public void change_footer(T generic_param, int value) {
generic_param.setFooter(value);
}
}
Class HelloWorld
public class HelloWorld{
public static void main(String []args){
Here I want to call
A a = new A();
new D().change_footer(a, 5);
B b = new B();
new D().change_footer(b, 5)
}
}
Thank You
And if I got all of the question wrong, and nor A nor B are generic, AND the type of field is fixed.
then you mean something like:
class D {
/*public <T extends Super> would be muuuch nicer here as well!*/
public /*static*/ <T> void change_footer(T obj, int data) {
//otherwise, you could just cast to Super...and set dat field.
if (obj instanceof A) {
((A) obj).setField(data);
} else if (obj instanceof B) {
((B) obj).setField(data);
} // else ... ?
}
}
Original answer:
Easy peasy (the "straight forward" implementation produces the desired results.):
class A<T> {
T daField;
public void setField(T pField) {
daField = pField;
}
public T getField() {
return daField;
}
}
class B<T> extends A {//empty
}
class Test {
public static void main(String... args) {
B<Object> testB1 = new B<>(); //
testB1.setField(new Object());
System.out.println(testB1.getField());
B<String> testB2 = new B<>();
testB2.setField("blah blah");
System.out.println(testB2.getField());
B<Integer> testB3 = new B<>();
testB3.setField(42);
System.out.println(testB3.getField());
}
}
System.out:
java.lang.Object#6d06d69c
blah blah
42
It get's (little) more complicated, when you want to instantiate Ts ...but still possible/other question. :)
Edit to your comment:
If there's only one common field, then why not:
/*abstract */class Super<T> {
T daField;
public void setField(T pField) {
daField = pField;
}
public T getField() {
return daField;
}
}
? ...and:
class A<T> extends Super { ... }
class B<T> extends Super { ... }

Java Template invocation - runtime deduction

I was learning Java templates. As generics are compiled, I was hoping runtime deduction of type and hence invocation accordingly.
Seems it doesn't. i.e. deduction is based on compile time type deduction, although template itself is compiled.
Test Interface:
interface op {
public Object Do(Object o);
public Class getClass1();
public Object getTest();
}
Interface implementation
class intop implements op{
public Object Do(Object o) {
return (Integer) o;
}
public Class getClass1() {
return Integer.class;
}
public Object getTest() {
return new Integer(1);
}
}
class strop implements op{
public Object Do(Object o) {
return (String) o;
}
public Class getClass1() {
return String.class;
}
public Object getTest() {
return "Test";
}
}
Template & Specilizations
class Utils {
public static void performOp(Integer i) {
System.out.println("Interger Object :" + i);
}
public static void performOp(String s) {
System.out.println("String object : " + s);
}
public static <T> void performOp(T o) {
System.out.println("Generic Object :" + o.toString());
}
}
Testing
public class GenMethod {
public static void main(String args[]) {
Utils.performOp(1);
Utils.performOp("Test");
Utils u = new Utils();
Integer i = 4;
Object o = i;
ArrayList<op> a = new ArrayList<op>();
a.add(new intop());
a.add(new strop());
Random rn = new Random();
op b = a.get(rn.nextInt(2));
Utils.performOp(b.getClass1().cast(b.getTest()));
Utils.performOp(u);
}
}
I was Expecting output to be something like:
Interger Object :1
String object : Test
Interger Object :1
Generic Object :Utils#64c3c749
But It was :
Interger Object :1
String object : Test
Generic Object :1
Generic Object :Utils#3ce53108
Is there a way to correctly do specialized template method invocation based on runtime type deduction?
PS : I want to avoid the 'instanceof' & 'if..else' ladders as much as possible.

How can I refer to the type of the current class?

This is kind of difficult to explain, but I've looked everywhere, and I couldn't find any good answer.
I've also seen Stack Overflow questions How can I refer to the class type a interface is implementing in Java? and How do I return an instance of an object of the same type as the class passed in using Java 6?, but they couldn't answer my question. There is an exception when I apply inheritance.
There is an example, to make it easier to understand:
Let's say I have some interface called SelfMaker:
public interface SelfMaker <SELF>{
public SELF getSelf();
}
And A have a Dog, which can procreate with another dogs. So the dog is a "SelfMaker", like this:
public class Dog implements SelfMaker<Dog> {
String color;
public String toString() {
return "some " + color + " dog";
}
public Dog procreate(Dog anotherDog) {
Dog son = getSelf();
son.color = color;
return son;
}
#Override
public Dog getSelf() {
return new Dog();
}
}
But then, I have a DomesticDog, who is a Dog, but it has a lovely family who named him. Like this:
public class DomesticDog extends Dog {
private String name;
public String toString() {
return super.toString() + " named " + name;
}
}
Now, I have some class that handles couples of things that are "SelfMaker"s, let's call this class "Couple". Like this:
public class Couple<T extends SelfMaker<T>> {
private T first;
private T second;
public String toString() {
return first.toString() + " and " + second.toString();
}
}
THE EXCEPTION:
The exception comes when I want to create a couple of DomesticDogs. Like this:
public class CoupleOfDomesticDogs extends Couple<DomesticDog>{
public DomesticDog procreate(){
DomesticDog son = first.procreate(second);
return son;
}
}
This will throw an exception on <DomesticDog> complaining: Bound mismatch: The type DomesticDog is not a valid substitute for the bounded parameter <T extends SelfMaker<T>> of the type Couple<T>
I have already tried to change the generalised variable from class Couple to this: Couple<T extends SelfMaker<?>> but the "son" won't be a DomesticDog (and I want the "son" to be a DomesticDog). If I add some cast, then it will compile, but it will be less legible.
So... here is the question: Is there a way to achieve this without castings and generalizations?
There is no way that I can think of to do this without casting. Your problem will be solved if you override the procreate and getSelf methods of DomesticDog and change the declaration of class Couple as such:
public class DomesticDog extends Dog {
private String name;
public DomesticDog procreate(Dog anotherDog) {
return (DomesticDog)super.procreate(anotherDog);
}
public Dog getSelf() {
return new DomesticDog();
}
public String toString() {
return super.toString() + " named " + name;
}
}
public class Couple<T extends SelfMaker<? super T>> {
protected T first;
protected T second;
public String toString() {
return first.toString() + " and " + second.toString();
}
}
If you don't want to override getSelf() in every subclass of Dog, you could make the following change in class Dog:
public Dog getSelf() {
Class<? extends Dog> thisClass = this.getClass();
try {
return thisClass.newInstance();
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
}
throw new UnsupportedOperationException(thisClass
+ " does not supply a public no-arg constructor");
}
This guarantees that every value returned by getSelf() is an instance of this.getClass(). But you would still have to cast the return value of procreate() for subclasses. There is no way to explicitly specify a return type as this.getClass().
You will have to make Dog generic and abstract, with a type parameter that indicates the result of getSelf(). Each type of Dog will then need to implement this with themselves as the parameter:
public abstract class Dog<T> implements SelfMaker<T> {
String color;
public String toString() {
return "some " + color + " dog";
}
public T procreate(T anotherDog) {
T son = getSelf();
son.color = color;
return son;
}
}
public class DomesticDog extends Dog<DomesticDog> {
private String name;
public String toString() {
return super.toString() + " named " + name;
}
#Override
public DomesticDog getSelf() {
return new DomesticDog();
}
}

Java: Class.this

I have a Java program that looks like this.
public class LocalScreen {
public void onMake() {
aFuncCall(LocalScreen.this, oneString, twoString);
}
}
What does LocalScreen.this means in aFuncCall?
LocalScreen.this refers to this of the enclosing class.
This example should explain it:
public class LocalScreen {
public void method() {
new Runnable() {
public void run() {
// Prints "An anonymous Runnable"
System.out.println(this.toString());
// Prints "A LocalScreen object"
System.out.println(LocalScreen.this.toString());
// Won't compile! 'this' is a Runnable!
onMake(this);
// Compiles! Refers to enclosing object
onMake(LocalScreen.this);
}
public String toString() {
return "An anonymous Runnable!";
}
}.run();
}
public String toString() { return "A LocalScreen object"; }
public void onMake(LocalScreen ls) { /* ... */ }
public static void main(String[] args) {
new LocalScreen().method();
}
}
Output:
An anonymous Runnable!
A LocalScreen object
This post has been rewritten as an article here.
It means the this instance of the outer LocalScreen class.
Writing this without a qualifier will return the instance of the inner class that the call is inside of.
The compiler takes the code and does something like this with it:
public class LocalScreen
{
public void method()
{
new LocalScreen$1(this).run;
}
public String toString()
{
return "A LocalScreen object";
}
public void onMake(LocalScreen ls) { /* ... */ }
public static void main(String[] args)
{
new LocalScreen().method();
}
}
class LocalScreen$1
extends Runnable
{
final LocalScreen $this;
LocalScreen$1(LocalScreen $this)
{
this.$this = $this;
}
public void run()
{
// Prints "An anonymous Runnable"
System.out.println(this.toString());
// Prints "A LocalScreen object"
System.out.println($this.toString());
// Won't compile! 'this' is a Runnable!
//onMake(this);
// Compiles! Refers to enclosing object
$this.onMake($this);
}
public String toString()
{
return "An anonymous Runnable!";
}
}
As you can see, when the compiler takes an inner class it converts it to an outer class (this was a design decision made a LONG time ago so that VMs did not need to be changed to understand inner classes).
When a non-static inner class is made it needs a reference to the parent so that it can call methods/access variables of the outer class.
The this inside of what was the inner class is not the proper type, you need to gain access to the outer class to get the right type for calling the onMake method.
Class.this allows access to instance of the outer class. See the following example.
public class A
{
final String name;
final B b;
A(String name) {
this.name = name;
this.b = new B(name + "-b");
}
class B
{
final String name;
final C c;
B(String name) {
this.name = name;
this.c = new C(name + "-c");
}
class C
{
final String name;
final D d;
C(String name) {
this.name = name;
this.d = new D(name + "-d");
}
class D
{
final String name;
D(String name) {
this.name = name;
}
void printMe()
{
System.out.println("D: " + D.this.name); // `this` of class D
System.out.println("C: " + C.this.name); // `this` of class C
System.out.println("B: " + B.this.name); // `this` of class B
System.out.println("A: " + A.this.name); // `this` of class A
}
}
}
}
static public void main(String ... args)
{
final A a = new A("a");
a.b.c.d.printMe();
}
}
Then you will get.
D: a-b-c-d
C: a-b-c
B: a-b
A: a
I know what is your confusion.I am encounter the problem just now, it should have special scene to distinguish them.
class THIS {
def andthen = {
new THIS {
println(THIS.this.## + ":inner-THIS.this.##")
println(this.## + ":inner-this.##")
new THIS {
println(THIS.this.## + ":inner-inner-THIS.this.##")
println(this.## + ":inner-this.##")
}
}
}
def getInfo = {
println(THIS.this.## + ":THIS.this.##")
println(this.## + ":this.##")
}
}
You can see the diff between THIS.this and this in new THIS operation by hashcode( .## )
test in scala console :
scala> val x = new THIS
x: THIS = THIS#5ab9b447
scala> val y = x.andthen
1522119751:inner-THIS.this.##
404586280:inner-this.##
1522119751:inner-inner-THIS.this.##
2027227708:inner-this.##
y: THIS = THIS$$anon$1#181d7f28
scala> x.getInfo
1522119751:THIS.this.##
1522119751:this.##
THIS.this always point to outer THIS class which is refer by val x,but this is beyond to anonymous new operation.

Inheritance in Java

Consider the following code in Python:
class A(object):
CLASS_ATTRIBUTE = 42
def f(self):
return "CLASS_ATTRIBUTE: %d" % self.CLASS_ATTRIBUTE
class B(A):
CLASS_ATTRIBUTE = 44
Now A().f() and B().f() return "CLASS_ATTRIBUTE: 42" and "CLASS_ATTRIBUTE: 44" respectively.
How can I achieve a similar effect in Java? I want a CLASS_ATTRIBUTE field to be initialized statically and redefined in the inherited class but the f method should be only defined in the base class.
Is there a particular reason you want the attribute to be static? In Java the typical way you'd do this is to have A contain a protected variable that you then set in the constructors of the 2 classes:
public class A
{
protected int CLASS_ATTRIBUTE;
public A()
{
CLASS_ATTRIBUTE = 42;
}
public String f()
{
return "CLASS_ATTRIBUTE: " + CLASS_ATTRIBUTE;
}
}
public class B extends A
{
public B()
{
CLASS_ATTRIBUTE = 44;
}
}
Alternatively (and probably more consistent with Java design patterns) you'd declare a function that you can override to return the value instead of using a member variable.
Short answer: you cant solve it like this in Java. You'll have to solve it in another way.
In Java you can't override or "redeclare" fields in subclasses, and you can't override static methods.
It can be solved using an ugly reflection-hack (should be avoided though):
public class Main {
public static void main(String... args) {
A a = new A();
B b = new B();
System.out.println(a.f()); // Prints 42.
System.out.println(a.fReflection()); // Prints 42.
System.out.println(b.f()); // Prints 42.
System.out.println(b.fReflection()); // Prints 44.
}
}
class A {
static int CLASS_ATTRIBUTE = 42;
public int f() {
return CLASS_ATTRIBUTE;
}
public int fReflection() {
try {
return getClass().getDeclaredField("CLASS_ATTRIBUTE").getInt(null);
} catch (Exception wontHappen) {
return -1;
}
}
}
class B extends A {
// Compiles, but will not "override" A.CLASS_ATTRIBUTE.
static int CLASS_ATTRIBUTE = 44;
}
You can't do this directly with only a variable, because in Java variables cannot override (they only shadow the super classes variables).
You need to use a protected "getter" method, which can then be overridden by the subclass:
class A
{
private int attribute=42;
...
protected int getAttribute() {
return attribute;
}
}
class B
extends A
{
private int attribute=44;
...
protected int getAttribute() {
return attribute;
}
}
But note there's a special consideration to calling methods from an object's constructor, in that it allows object code to run before object construction is complete.
I'm not sure if you meant "statically" literally or not, but here's a brief example of how inheritance at it's most basic form looks in Java. Note that using a getter method to access the variable is a better idea for several reasons -- this is just an example.
public class Dog {
protected String whatISay = "Woof!";
public void speak(){
System.out.println(whatISay);
}
}
public class Poodle extends Dog {
public Poodle(){
whatISay = "Yap!";
}
}
public class Main {
public static void main(String[] args){
Poodle fluffy = new Poodle();
fluffy.speak();
Dog dog = new Dog();
dog.speak();
}
}
Yap!
Woof!
This way of doing it introduces as little intrusion as I could think of. setAttribute() could be named something like setDefaultValue() if that's clearer.
public class A
{
protected int attribute;
public A()
{
setAttribute();
}
public String f()
{
return "CLASS_ATTRIBUTE: " + attribute;
}
protected void setAttribute()
{
attribute = 42;
}
}
public class B extends A
{
#Override
protected void setAttribute()
{
attribute = 44;
}
}
public class Main
{
public static void main(String[] args)
{
A a = new A();
B b = new B();
System.out.println("A: " + a.f());
System.out.println("B: " + b.f());
}
}

Categories

Resources