-2

I have 2 classes

class Immutable {
    public int i;
    public static Immutable create(int i){
        return new Immutable(i);
    }
    private Immutable(int i){this.i = i;}
    public int getI(){return i;}
}

and

class Immutable1 {
    public int i;
    public static Immutable1 create(int i){
        return new Immutable1(i);
    }
    private Immutable1(int i){this.i = i;}
    public int getI(){return i;}
}

Both have same methods and same instance variables. As per my understanding state of the class are same (int i) and both have same behaviour(same number of methods)

Hence one is exact copy of another.

In another class if I do

Immutable immutable=Immutable.create(1);
    Immutable1 immutable1=Immutable1.create(1);
    immutable1=immutable;// I get error here

The error is type mismatch :can not convert from Immutable to Immutable1

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
rocking
  • 4,729
  • 9
  • 30
  • 45

4 Answers4

1

Java uses nominative typing (only the names, and what is declared to inherit/implement what matter). The question is describing structural typing which Java does not support.

In this case there is a trivial type error because there is no declared nominative relationship between the Immutable and Immutable1 types.

Now, even if there was an relation, keep in mind that only a subtype can be implicitly assigned to a supertype; the opposite is not possible without an explicit downcast cast that can fail at run-time.

Thus the current code would be type-valid if, and only if, Immutable extends Immutable1 - ie. class Immutable extends Immutable1 ..


Andrey points out another solution, that I quite like, which is to have both classes implement the same interface. This still uses nominative typing - as both classes are only type-equivalent insofar as they both implement ImmutableInterface - but eliminates the inheritance relationship between the classes.

interface ImmutableInterface {
    int getI();
}

class Immutable implements ImmutableInterface ..
class Immutable1 implements ImmutableInterface ..

// The resulting object types are implicitly upcast to
// the common (and named) interface type which is trivially assignable to
// a variable of the same type; no need to worry about subtypes here.
ImmutableInterface immutable=Immutable.create(1);
ImmutableInterface immutable1=Immutable1.create(1);
immutable1 = immutable;
Community
  • 1
  • 1
user2864740
  • 60,010
  • 15
  • 145
  • 220
  • even if i do immutable extends immutable1 then also error **Implicit super constructor Immutable1() is undefined. Must explicitly invoke another constructor** – rocking Aug 15 '15 at 18:49
  • @rocking In this case the 'fix' would be to add `super(i);` at the top of the constructor - and make the parent constructor `protected`, not `private`. (Search for that error as to what causes it as there are no shortage of duplicates.) – user2864740 Aug 15 '15 at 18:50
  • Both classes may implement the same interface, e.g. `ImmutableInterface`. In this case there'd be no need to fix constructors. – Andrey Aug 15 '15 at 18:54
  • @user2864740 is it necessary to call super(i) if yes why – rocking Aug 15 '15 at 18:58
  • @Andrey That is indeed a better approach. I've boxed my answer in to trying to work with the current code, but have updated it - thanks. – user2864740 Aug 15 '15 at 18:58
  • @rocking Yes, because there is no default constructor available in the parent type. Search for the error message for details. This is not needed if using interfaces (as then there is no class subtype relationship established). – user2864740 Aug 15 '15 at 18:59
  • @user2864740 I am confused why you had used interface. As per my understanding functions(like dog eats) means methods in java. As both the classes have same functions so you have used interface. But what about instance variables. If I give different instance variables then also both the objects are showing equal – rocking Aug 15 '15 at 19:09
  • @rocking Check the [marker interface pattern](http://stackoverflow.com/questions/1995198/what-is-the-use-of-marker-interfaces-in-java). – Andrey Aug 15 '15 at 19:11
  • @Andrey marker interface has nothing that is no methods but here ImmutableInterface has getI() method.So how are they both related – rocking Aug 15 '15 at 19:22
  • @rocking In this particular case the only reason we use an interface is to create a type relationship between the two otherwise unrelated classes. Nothing changes if this interface has no methods at all (marker interface). So the point is to provide a shared type, not a shared functionality. I'd recommend to read [Java tutorial on interfaces and inheritance](https://docs.oracle.com/javase/tutorial/java/IandI/index.html). – Andrey Aug 15 '15 at 19:33
0

Just because the classes are declared with the same fields and methods, it does NOT mean they are the SAME class. To Java, they are very distinct, because they have different names.

Now, if you for some reason really need two (or more) distinct classes, but also be able to use them in a common manner, you should make both (all) of them implement a common interface.

Andreas
  • 154,647
  • 11
  • 152
  • 247
0

I dont know why you would like to create two different classes doing exactly the same thing and compare if some instances are equals... Do you know you can instanciate multiple objects from the same class ?

Then if you really want to compare an instance of Immutable1 with an instance of Immutable you ll have to decide by your own what make them 'equals'. For exemple you can try

public boolean myCustomEqualMethod(Immutable1 i1, Immutable i2){
        return i1.getI()==i2.getI();
    }

More over you dont test equality with '='. For primitives types it is '==' and for other objects you have to call the equals method:

boolean equalsOrNot="chaine1".equals("chaine2");
Erwan C.
  • 709
  • 5
  • 18
0

For comparing two objects you use equals method present in Object class. What are you trying to achieve by creating Immutable classes. Immutable objects are ones which you cannot change like String in java. If you change it like

String str ="XYZ";
str="XZY";

What excatly is happening is :- str is holding a memory address of XYZ(say 1346) and now str is holding a memory address of XZY(say 6733) which are different because Strings are immutable.

Goyal Vicky
  • 1,249
  • 16
  • 16
  • I agree that I am creating immutable class but my question even if both have same properties still why can not be both same? – rocking Aug 15 '15 at 18:46
  • Giving same value to 2 objects does not make it equal for java. It may be equal for you not for java. To understand better try to explore hashCode and equals method used in HashMap or HashSet in java. – Goyal Vicky Aug 15 '15 at 18:50