0

I am working on a small project where I have Classes Country, Population and Continent.

Both of the Classes Population and Continent use Enums to define possible values. Where in Country I want to use "factory methods" to create new Countries. Code follows:

public enum Continent {
    EUROPE, 
    ASIA, 
    AMERICA;
}

public enum Population {
    LOW(1000000),
    AVERAGE(2000000),
    HIGH(5000000); 
} 

public class Country{  

    private Continent=null;  
    private Population=null;

    Country(Continent continent, Population population){  
        this.continent=continent;  
        this.population=population;  
    }

Ok so my problem is that I tried to override my equals() function, but it doesn't give me the expected results.

public boolean equals(Country other){  
    if(this.population == other.population && this.continent==other.continent)
        return true;
    else 
        return false;  
}

But the assertions tests are giving me the following results back

java.lang.AssertionError: [new Country(Europe,HIGH)] Expecting:
<"Romania (Country@464a7b61)"> to be equal to: <"Romania (Country@488d8dd8)">
but was not.

I was looking online, and what I have found was that when same parameters are given it should know it is the same one, e.g. there should not be two different objects for same parameters. I am sure if I have understood it correctly, but it seemed relevant.

I still don`t know if that is the case and how to approach it. Ideas?

UPDATE:
After some suggestions appeared I tried changing the equals function to

public boolean equals(Country other){  
    if(this.population.equals(other.population) && this.continent.equals(other.continent))
        return true;
    else 
        return false;  
}

UPDATE 2:

public boolean equals(Object o){  
    if(this.population.equals(o.population) && this.continent.equals(o.continent))
        return true;
    else 
        return false;  
}  

It is not allowing me to do .population and .continent

Christoph Grimmer
  • 4,210
  • 4
  • 40
  • 64

5 Answers5

3

You have the wrong signature for your equals() method

It should read:

  @Override
  public boolean equals(Object o) {

Note the Object o instead of Country

Rob Audenaerde
  • 19,195
  • 10
  • 76
  • 121
  • thanks, I have updated the problem. Now I can`t check if they are of the same continent or population – Tricker Macedonia Aug 27 '18 at 11:36
  • You need to explicitly cast the object to access it's fields. Your code does not compile like this. – Rob Audenaerde Aug 27 '18 at 11:37
  • okay I fixed it like you said, but I still don't get TRUE. Could it be that I need to override the hashfunction as well? I mean it seems like it has created two Countries Romania which are saved on different places, but there should be only one – Tricker Macedonia Aug 27 '18 at 11:44
  • No, you have two instances of `Romania` but using the same annotations (if done properly). This is why you need an `equals` method. Or `romania1 == romania2` would work. Please show us your testing too. – AxelH Aug 27 '18 at 11:48
0

You are missing @Override annotation. Also you do not forward a Country but Object

mirzak
  • 1,043
  • 4
  • 15
  • 30
0

Some basics about object oriented programming:

When you derive from a class (e.g. Object) and you want to override a method in the super class you need to match the signature of that method. In your case you're overriding Object::equals so you need to match its signature.

As @RobAu wrote this is

public boolean equals (Object o)  

which in turn means that your compiler will not allow you to use access any members of the sub-class. That's why you need to (a) check the class of the argument and (b) do a hard cast to Country.

As an alternative you could use a library like Lombok which will generate a typical equals/hash combo for you (see https://projectlombok.org/features/EqualsAndHashCode)

Happy coding.

Christoph Grimmer
  • 4,210
  • 4
  • 40
  • 64
0

In addition to the change in signature the other answers pointed out, you will need to check if the argument is of type Country. Only if it is you can access its attributes. The following code does this:

public boolean equals(Object o) {
    if(!(o instanceof Country))
         return false;
    Country c = (Country) o;
    if(this.population.equals(c.population) && this.continent.equals(c.continent))
        return true;
    return false;  
}
O.O.Balance
  • 2,930
  • 5
  • 23
  • 35
-1

You should implement/override the equals in your enum and then use the .equals operator in your method to compare two enums. Additionally, you forgot the @Override annotation, so this method is never called because it is not known that you have overriden it.

ItFreak
  • 2,299
  • 5
  • 21
  • 45
  • @Override, while highly encouraged, is not necessary. It is good to use it (in this case, the compiler would have thrown an error since he wasn't overriding the proper method), but if equals(Object obj) is overriden, it willl work, no matter if the annotation is used. – Silverlord Aug 27 '18 at 11:28
  • 1
    "_this method is never called because it is not known that you have overriden it._" that's not how the annotation works or even why it exist. This one is only used for the developer I believe to easily point that a method is overriden. The annontation `@Override` is optional – AxelH Aug 27 '18 at 11:34
  • but initially he didn't override the correct method so using it (like almots everyone) would have saved him:) – ItFreak Aug 27 '18 at 12:07
  • 1
    Do not use equals with enums. Equals removes type safety and allows you to mistakenly compare two different types of enums (which is useless as they always return false). The == operator makes the compiler guarantee that you don't do silly things. Trust me, I have seen the feet and the bullet wounds. :) – Torben Aug 27 '18 at 12:18