8 Replies - 372 Views - Last Post: 03 August 2013 - 05:01 AM Rate Topic: ****- 3 Votes

#1 MasterZeddicus  Icon User is offline

  • New D.I.C Head

Reputation: 6
  • View blog
  • Posts: 39
  • Joined: 30-January 12

Inheritence/Polymorphism question regarding equals method.

Posted 01 August 2013 - 11:05 PM

Alright so here I go, this is a bit of a weird issue that I'm stuck on. Essentially I have an abstract class as my base for a project, the abstract class is for the crew of a hospital and contains the various instance variables common to all crew subclasses, an enumerated data type for gender, and my various methods I wish to have implemented and overridden in later classes, now my toString override works perfectly and as intended, but using the same logic with my equals method does not. First I'll explain my method so if my methodology is incorrect a more experienced user can point it out.

Basically in the abstract class for toString I've done the following:
public String toString(){
		return("Crew members name: " + name + "\n sex: " + sex + "\n Age: " + age + "\n Date of Birth: " + dOB 
				+ "\n Address: " + address + "\nSocial insurance no: " + sIN);				
	}


then in further classes I've appended it in an override method to include the following:
public String toString(){
		return(super.toString() + "\n Patients Physician is: " + assignedPhysician);
	}


This works flawlessly and produces the same string from the abstract class with the appended assignedPhysician string which is stored.

Now I wanted to do the same thing with the equals method, sorry for the long code. I'm not sure if there is a problem with my method itself, the fact that I'm using an enumerated type, or what. (equals method is on line 111)

crew abstract base class
/**
 * This is our crew abstract class which will serve as a template for all members of the hospital.
 * This is our base class
 * @author Zeddikus J. Hargrave 5383290
 * @version 1.0
 * 
 */
public abstract class Crew {

/**
 * This enumerated type is for the Sex of our crew, since there are only two options it makes sense to use
 * an enumerated type with a valid toString override. 	
 */
	public enum Sex {MALE, FEMALE;
	
	public String toString(){
			if (this == MALE)
				return "Male";
			else
				return "Female";
		}
	} 
	
	/**
	 * @param name The crew members name. 
	 * @param age Self explanatory.
	 * @param sex The sex of the crew member.
	 * @param sIN The social insurance no. of the crew member. 
	 * @param address The crew members mailing address 
	 * @param dOB The crew members date of birth as a string 
	 */	
	
	private Sex sex; 
	private int age; 
	private String name;
	private int sIN; 
	private String address; 
	private String dOB; //Since there are no calculations related to date of birth it's simple to store it as a string.
	
	/**
	 * Constructors
	 */
	
	public Crew(){
		sex = Sex.MALE;
		age = 18;
		name = "John Doe";
		sIN = 999999999;
		address = "123 fake street, HHHHHH, Montreal";
		dOB = "July 22nd 2999";		
	}
	
	public Crew(Sex sex, int age, String name, int sIN, String address, String dOB){
		this.sex = sex; 
		this.age = age; 
		this.name = name; 
		this.sIN = sIN; 
		this.address = address; 
		this.dOB = dOB; 
	}
	
	/** 
	 * Accessors
	 * 
	 */
	
	public Sex getSex(){return sex;}	
	public int getAge(){return age;}
	
	/**
	 * Since strings are objects and we don't want to return the actual address since this would 
	 * destroy the point of having the string private we must make a copy and return the address of the
	 * copy instead of the original. (Due to pass by value.)
	 */ 
	public String getName(){
		String s = new String(this.name);
		return s; 
	}
	
	public int getSIN(){return sIN;}
	
	public String getAddress(){
		String s = new String(this.address);
		return s; 
	}
	
	public String getDOB(){
		String s = new String(this.dOB);
		return s; 
	}
	/**
	 * Mutators
	 */
	
	public void setSex(Sex sex){this.sex = sex;}
	public void setAge(int age){this.age = age;}
	public void setName(String name){this.name = name;}
	public void setSIN(int sin){this.sIN = sin;}
	public void setAddress(String address){this.address = address;}
	public void setDOB(String dOB){this.dOB = dOB;}
	
	
	/**
	 * toString and equals methods (to be further appended with overrides in derrived classes
	 */
	
	public String toString(){
		return("Crew members name: " + name + "\n sex: " + sex + "\n Age: " + age + "\n Date of Birth: " + dOB 
				+ "\n Address: " + address + "\nSocial insurance no: " + sIN);				
	}
	public boolean equals(Object o){
		if (this == null || o == null || this.getClass()!= o.getClass())
			return false; 
		else
		{
			Crew c = (Crew) o;
			return (this.sex == c.getSex() && this.age == c.getAge() && this.name.equals(c.getName()) 
					&& this.sIN == c.getSIN() && this.address.equals(c.getAddress()) && this.dOB.equals(c.getAddress()));
		}
		
		
	}
}

	




Here is the patient subclass as mentioned: (equals method is on line 37)
public class Patient extends Crew {
	
	private int count = 0; //gives us the number of patients in the hospital	
	private String assignedPhysician; //Lists the name of the Physician attached to the patient.
	
	public Patient() {
		super();
		assignedPhysician = "NONE";
		System.out.println("Creating a default patient, please note this patient is UNDEFINED");
		count++; 
	}

	public Patient (Sex sex, int age, String name, int sIN, String address, String dOB, String assignedPhysician){
		super(sex, age, name, sIN, address, dOB);
		this.assignedPhysician = assignedPhysician; 
		System.out.println("Creating a patient with the given information");
		count++;
	}
	
	public void reduceCount(){ //used only when a patient is removed from the hospital
		count--; 
	}
	
	public String getAssignedPhysician(){
		String s = new String(assignedPhysician);
		return s; 
	}
	
	public void setAssignedPhysician(String physician){
		this.assignedPhysician = physician; 		
	}
	
	public String toString(){
		return(super.toString() + "\n Patients Physician is: " + assignedPhysician);
	}
	
	public boolean equals(Object o){
		if(!super.equals(o))
			return false; 
		else{
			Patient v = (Patient) o; 
			return (this.assignedPhysician.equals(v.getAssignedPhysician()));
		}
	}
}


And lastly the driver class I created for testing the constructor, toString, and equals methods.

public class Hospital {

	/**
	 * @param argssuper(sex, age, name, sIN, address, dOB);
	 */
	public static void main(String[] args) {
		
		Patient patient01 = new Patient();
		Patient patient02 = new Patient(Crew.Sex.MALE, 24, "John Hancock", 743722734, "12344 fhskh, GGGA", "July 22, 1989","Dr Rexy");
		Patient patient03 = new Patient(Crew.Sex.MALE, 24, "John Hancock", 743722734, "12344 fhskh, GGGA", "July 22, 1989","Dr Rexy");
		System.out.println(patient01);
		System.out.println();
		System.out.println(patient02);
		System.out.println();
		System.out.println(patient03);
		System.out.println();
		
		if(patient01.equals(patient02))
			System.out.println("Patients 1 and 2 are equal\n");
		else
			System.out.println("Patients 1 and 2 are different\n");
		if(patient02.equals(patient03))
			System.out.println("Patients 2 and 3 are equal\n");
		else
			System.out.println("Patients 2 and 3 are different\n");

	}

}


Here is the output:
Creating a default patient, please note this patient is UNDEFINED
Creating a patient with the given information
Creating a patient with the given information
Crew members name: John Doe
 sex: Male
 Age: 18
 Date of Birth: July 22nd 2999
 Address: 123 fake street, HHHHHH, Montreal
Social insurance no: 999999999
 Patients Physician is: NONE

Crew members name: John Hancock
 sex: Male
 Age: 24
 Date of Birth: July 22, 1989
 Address: 12344 fhskh, GGGA
Social insurance no: 743722734
 Patients Physician is: Dr Rexy

Crew members name: John Hancock
 sex: Male
 Age: 24
 Date of Birth: July 22, 1989
 Address: 12344 fhskh, GGGA
Social insurance no: 743722734
 Patients Physician is: Dr Rexy

Patients 1 and 2 are different

Patients 2 and 3 are different


I'm really stumped as to why it's coming back with them as different, I'm just not sure how to proceed. I would hate to have to completely define the equals method for every subclass as I have about 8 or 9 I'm working with, not to mention the point of inheritance is to reuse code. If anyone can point me in the right direction I'd be very happy. Sadly no matter how many coffee beans I inject I can't seem to get this one going haha.

Warmest Regards
Zeddikus J. Hargrave

Is This A Good Question/Topic? 0
  • +

Replies To: Inheritence/Polymorphism question regarding equals method.

#2 salazar  Icon User is offline

  • D.I.C Addict

Reputation: 87
  • View blog
  • Posts: 539
  • Joined: 26-June 13

Re: Inheritence/Polymorphism question regarding equals method.

Posted 02 August 2013 - 12:06 AM

Look at what your doing in the equals method of the patient class. Maybe it has something to do with comparing the super classes. It looks like your comparing the currents class's super class with the others child class. This probably sounds confusing. Just take a look at the super.

I ran it through a debugger and I believe it be stemming from the equal method of the Crea class.

This post has been edited by salazar: 02 August 2013 - 12:42 AM

Was This Post Helpful? 0
  • +
  • -

#3 MasterZeddicus  Icon User is offline

  • New D.I.C Head

Reputation: 6
  • View blog
  • Posts: 39
  • Joined: 30-January 12

Re: Inheritence/Polymorphism question regarding equals method.

Posted 02 August 2013 - 12:30 AM

I don't see how that is possible, if I look at the two classes methods:

(extracted from the patient class)
public boolean equals(Object o){
		if(!super.equals(o))
			return false; 
		else{
			Patient v = (Patient) o; 
			return (this.assignedPhysician.equals(v.getAssignedPhysician()));
		}


(extracted from my super class crew.
public boolean equals(Object o){
		if (this == null || o == null || this.getClass()!= o.getClass())
			return false; 
		else
		{
			Crew c = (Crew) o;
			return (this.sex == c.getSex() && this.age == c.getAge() && this.name.equals(c.getName()) 
					&& this.sIN == c.getSIN() && this.address.equals(c.getAddress()) && this.dOB.equals(c.getAddress()));
		}



bearing in mind all subclasses also have the class of their parents and ancestors I believe what should be happening is I'm making a call for

patient02.equals(patient03);

when this goes into the patient class, it is the object patient02.
Patient02 executes this.super.equals(o)
which technically says take the crew portion of patient02 and see if it equals our object o.
Since no explicit casting is done and my super class is happy to accept a form in the object of o, by my understanding, neither this, or o will be equal to null. When this.getClass() and o.getClass() are looked for they will find the same class, both objects have the following classes:Object,Crew, and Patient. It then just compares the specific values to crew, and returns true or false, if it returns true flow of control is returned back to my equals method with a true flag, o is casted as a Patient and then checked for the same assigned physician string.

It may be an issue with the super keyword that I'm not aware of, but I don't see calling o's superclass doing anything, and the super keyword would not even work in that case as super is always read by the JVM as this.super. I feel as though this may be an issue with casting o as a Crew then returning to the method and casing o as a Patient? I don't see why though as no information should be lost when it is cast, but maybe it is.


EDIT: It's definitely not a casting issue causing loss of data, I checked with a second set of prints after the objects are casted and passed around they are still identical. I also tried passing o with a downcast to Crew to see if it would make a difference in the line with !super.equals((Crew)o), just to see if it was an issue with comparing the classes of super like you suggested, but no go.

This post has been edited by MasterZeddicus: 02 August 2013 - 12:36 AM

Was This Post Helpful? 0
  • +
  • -

#4 salazar  Icon User is offline

  • D.I.C Addict

Reputation: 87
  • View blog
  • Posts: 539
  • Joined: 26-June 13

Re: Inheritence/Polymorphism question regarding equals method.

Posted 02 August 2013 - 01:03 AM

Yeah, sorry, I did catch my self on that. It's probably not the problem, you're correct. I ran you program again through a debugger, and I am pretty certain it's coming from the Crew class, specifically the else clause of the in the equals method. For some reason, it is returning false.
Was This Post Helpful? 0
  • +
  • -

#5 salazar  Icon User is offline

  • D.I.C Addict

Reputation: 87
  • View blog
  • Posts: 539
  • Joined: 26-June 13

Re: Inheritence/Polymorphism question regarding equals method.

Posted 02 August 2013 - 01:14 AM

I found your error. You're accidently calling the getAddress() method when comparing the dob. It was probably all those conditions in the if statement that made it hard to spot.

This post has been edited by salazar: 02 August 2013 - 01:42 AM

Was This Post Helpful? 2
  • +
  • -

#6 MasterZeddicus  Icon User is offline

  • New D.I.C Head

Reputation: 6
  • View blog
  • Posts: 39
  • Joined: 30-January 12

Re: Inheritence/Polymorphism question regarding equals method.

Posted 02 August 2013 - 01:24 AM

UGH after hours I had just found this, and saw your post. What a novice mistake, and a dumb error not to check for. I ran it through the eclipse debugger and saw which method was being pointed to. What a pain lol. Ah well, at least I know it wasn't an error in my logic.

Thanks for your help and spending the time debuggin!

To whatever mod passes by, this topic can be closed now.

This post has been edited by MasterZeddicus: 02 August 2013 - 01:26 AM

Was This Post Helpful? 0
  • +
  • -

#7 salazar  Icon User is offline

  • D.I.C Addict

Reputation: 87
  • View blog
  • Posts: 539
  • Joined: 26-June 13

Re: Inheritence/Polymorphism question regarding equals method.

Posted 02 August 2013 - 01:36 AM

Yeah, I guess I know why it is recommend to not put so many condition in a single if statement. When then you could do is separate each condition onto its own line. This would make it a lot easier to spot the error. :smile2:

This post has been edited by salazar: 02 August 2013 - 01:40 AM

Was This Post Helpful? 1
  • +
  • -

#8 g00se  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 2699
  • View blog
  • Posts: 11,367
  • Joined: 20-September 08

Re: Inheritence/Polymorphism question regarding equals method.

Posted 02 August 2013 - 01:40 AM

salazar is right:
return (this.sex == c.getSex() && this.age == c.getAge() && this.name.equals(c.getName()) && this.sIN == c.getSIN() && this.address.equals(c.getAddress()) && this.dOB.equals(c.getDOB()));

is what you need

This post has been edited by g00se: 02 August 2013 - 01:41 AM
Reason for edit:: typo

Was This Post Helpful? 0
  • +
  • -

#9 pbl  Icon User is offline

  • There is nothing you can't do with a JTable
  • member icon

Reputation: 8329
  • View blog
  • Posts: 31,857
  • Joined: 06-March 08

Re: Inheritence/Polymorphism question regarding equals method.

Posted 03 August 2013 - 05:01 AM

Avoid long combination of && like this

	return (this.sex == c.getSex() && this.age == c.getAge() && this.name.equals(c.getName()) 
					&& this.sIN == c.getSIN() && this.address.equals(c.getAddress()) && this.dOB.equals(c.getAddress()));


use rather multiple tests and return if a condition is not met
and be consistent if you use the getter use it for both (this and c) so
this.getSex() == c.getSex() or this.sex == c.sex
   if(this.sex != c.sex)
      return false;
   if(this.age != c.age)
      return false;
   if(!this.name.equals(c.name))
      return false;
   ...
   return true;  // <--- ok all the same


Actually all these tests are most probably irrelevant. Two patients may have the same name, just checking the SIN should be sufficient
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1