• Post Reply Bookmark Topic Watch Topic
  • New Topic

Polymorphism issue  RSS feed

 
Alexandros Stefanidis
Greenhorn
Posts: 20
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi I have following code:



The code compiles and runs successfully.
How can I use the super keyword in printInfo() of MarriedPerson class to replace existing code and do the same job?
 
Carey Brown
Bartender
Posts: 3009
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

I suggest using toString(), and then printing the string elsewhere.
 
Campbell Ritchie
Marshal
Posts: 55768
163
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the Ranch

I like to put that sort of thing into one statement if I can:-You can use the String#format() method to create such a String as an alternative.
Avoid += on Strings because it can lead to slow performance. Avoid == false, too. Use the bang sign ! for not.
 
Paul Clapham
Sheriff
Posts: 22509
43
Eclipse IDE Firefox Browser MySQL Database
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I like to use a ChoiceFormat for that, because not only does it simplify that code, it takes care of an issue you missed. Have a look at the tutorial: https://docs.oracle.com/javase/tutorial/i18n/format/choiceFormat.html



 
Campbell Ritchie
Marshal
Posts: 55768
163
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I never knew about choice format. Thank you
 
Alexandros Stefanidis
Greenhorn
Posts: 20
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I want to keep the printInfo() so I have written the following:

In Person:



In MarriedPerson:



I get in my output:

Paul Kings is 22 years old, gets a 1200.0 Euros salary and is married.
Betty Tront is 31 years old, gets a 980.5 Euros salary and is married.
with 3 children

How can I get in my output the following:
Paul Kings is 22 years old, gets a 1200.0 Euros salary and is married.
Betty Tront is 31 years old, gets a 980.5 Euros salary and is married with 3 children.
 
Campbell Ritchie
Marshal
Posts: 55768
163
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I suggest you don't write a printInfo method, but override the toString() method.Whatever you had in the printInfo class, move it to toString but no print calls. Everything to be returned. In the subclass, use one of that cheat Campbell Ritchie's naughty tricks:-Try the backspace character which will probably allow you to overwrite the full stop
If you want a printInfo method, you don't need to override it in the subclass. It is much simpler than you think now:-If you go looking for System.out.println, after about 6‑8 clicks you find out that the toString method is called, so you now know what is printed out.
 
Alexandros Stefanidis
Greenhorn
Posts: 20
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi! First I have pressed button that this topic is resolved. But is not yet. Is there a way to undo that.
Second I have expanded the code:







My output is:
Paul Kings is 22 years old, male, gets a 1200.0 Euros salary and is not married.
Betty Tront is 31 years old, female, gets a 980.5 Euros salary and is married with 3 children.
Is mp1 married?: false

It seems that in second line that married variable is true.
In third line married variable is false.

How can I keep variable married unchanged when called via object mp1? Do I have to create a setMarried method in MarriedPerson class?
 
Carey Brown
Bartender
Posts: 3009
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
MarriedPerson Line 25 you've hard coded the outcome of 'married'.
 
Campbell Ritchie
Marshal
Posts: 55768
163
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, all married people are married. That isn't the real problem, I think. I think the real problem is having a married person class in the first place because people can change from one category (single) to the other and back (divorce, widowhood). It i;s very difficult to model such things in an inheritance hierarchy, and simply having a married field is probably better. Having a Condition (that is the official term) enum is better still:-
public enum Condition{ SINGLE, MARRIED, DIVORCED, WIDOWED; }
 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Alexandros Stefanidis wrote:How can I get in my output the following:
Betty Tront is 31 years old, gets a 980.5 Euros salary and is married with 3 children.

It's possibly worth mentioning that you're buying yourself a world of work (and possible mistakes) by requiring these "English" sentences. If you simply output attributes as a "list", there is far less to go wrong, viz:

  Betty Tront - age: 31; salary: 980.5 Euros; status: married; children: 3.

However, I strongly suspect some PHB (or tutor) asked you to do it, so it's probably not your fault.

Winston
 
Alexandros Stefanidis
Greenhorn
Posts: 20
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here is changed code:







Here is output:
Paul Kings is 22 years old, male, gets a 1200.0 Euros salary and is not married.
Betty Tront is 31 years old, female, gets a 980.5 Euros salary and is married with
3 children.
Is mp1 married?: true

It works as expected. One question though- In person class line 10 married variable from private boolean was changed to boolean. Is this liable?
 
Alexandros Stefanidis
Greenhorn
Posts: 20
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi!
to Winston Gutkowski - this is a Uni module excercise

Another question is to add a method setSalary in class MarriedPerson that will take as argument a MarriedPerson object named spouse and will do the following:

a) check spouse sex
b)If it is not the same with variable sex then in variable salary will be added the relevant variable of object spouse
c)if it the same nothing happens.

Also main have been changed to:



So according to above requirements I have written following code:





Basically I have added at line 41 of class MarriedPerson the method setSalary(MarriedPerson spouse)
and in line 11 of class Person I have removed the private access to salary.

Here is my output:

Betty Tront is 31 years old, female, gets a 980.5 Euros salary and is married with
3 children.
Kirk Tront is 31 years old, male, gets a 2080.0 Euros salary and is married with
2 children.
Sonia Tront is 31 years old, female, gets a 600.0 Euros salary and is married with
no children.
Betty Tront is 31 years old, female, gets a 3060.5 Euros salary and is married with
3 children.
Betty Tront is 31 years old, female, gets a 3060.5 Euros salary and is married with
3 children.
Betty Tront is 31 years old, female, gets a 2080.0 Euros salary and is married with
3 children.


I am not sure about the last output phrase.
 
Campbell Ritchie
Marshal
Posts: 55768
163
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Alexandros Stefanidis wrote:. . . Another question is to add a method setSalary in class MarriedPerson that will take as argument a MarriedPerson object named spouse and will do the following:

a) check spouse sex
b)If it is not the same with variable sex then in variable salary will be added the relevant variable of object spouse
c)if it the same nothing happens.
. . .
and in line 11 of class Person I have removed the private access to salary.
. . .
What a strange requirement, combining the salaries. What happens if you add a second spouse? Do you divorce the first one?
Removing private access looks like a serious mistake to me.
 
Alexandros Stefanidis
Greenhorn
Posts: 20
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If I keep the salary variable as private then I get the following error:

error: salary has private access in Person
this.salary += spouse.getSalary(); //line 44 in class MarriedPerson


thanks
 
Campbell Ritchie
Marshal
Posts: 55768
163
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Alexandros Stefanidis wrote:If I keep the salary variable as private then I get the following error:

error: salary has private access in Person
this.salary += spouse.getSalary(); //line 44 in class MarriedPerson


thanks
That is because you are not accessing the salary field correctly. You should be using getXXX and setXXX methods. Those will permit the changes without removing private access. You can also validate the input in a setXXX methodYou can also write an incrementSalary method which is rather similar.
 
Alexandros Stefanidis
Greenhorn
Posts: 20
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
to cambell Ritcie

Hi. I am doing this excersice sheet which has a question 5 that says
a) construct in every class for every method get or is a relevant method set so that you could change the values of variable instances.
b) Change the body of main in MyTester with following code:


Run and note the output. What do you observe?

c) Warning! Variable married for instances of class MarriedPerson should not change. Override method setMarried in class MarriedPErson so this doesn't happen.

So from above I have made the code:







My code is up to part b where I get the output:
Paul Kings is 22 years old, male, gets a 1200.0 Euros salary and is not married.
Betty Tront is 31 years old, female, gets a 980.5 Euros salary and is not married.3 children.
Is mp1 married?: false

I don't know how to do part c with get and set methods. I had removed keyword private from variable married which is not liable as you said.
 
Campbell Ritchie
Marshal
Posts: 55768
163
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think there is something wrong about having a married person class in the first place, but I think we cannot sort that problem out now. You can have single people turn into married people (that is called a wedding) and married people can turn into single people (that is sometimes called divorce), but you cannot turn a SinglePerson object into a MarriedPerson object or vice versa.

The fields should all be in the superclass. So should the setXXX and getXXX methods. Should the subclasses need to gain access to those data, they should use those methods, and should not have their own copies of the fields. In fact, the subclasses can become very short because they often do not require new methods or fields. If you are lucky, you can get away with writing constructors in subclasses and nothing else. You have managed quite a lot of that (‍) but there is something wrong with a MarriedPerson class where it is possible for isMarried to return false.
Your setMarried method on line 63 is unnecessarily complicated. In fact, it would make no difference if you simply wrote this.married = married;
Never use == false or == true. They are poor style and error‑prone if you write = by mistake.

Why have you not written a toString method, as I suggested last week?
 
Junilu Lacar
Sheriff
Posts: 11165
160
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have to say that this exercise is very poorly thought out and constructed. This is not a good example for polymorphism and the reasons have already been alluded to by others, especially by what Campbell is saying about being able to change from one status to another over time. The class name "MarriedPerson" is smelly because it carries a temporal (time based) state of a Person and makes it permanent. If you take that to the extreme, you could say that you should also have DivorcedPerson, SinglePerson, SeparatedPerson, WidowedPerson, etc. Taking that even further, you could have TeenAgePerson, ToddlerPerson, InfantPerson, SeniorPerson, etc. These are all arguably very poor design choices.

Just look at this part of the code and really think through whether it makes sense or not:

The above code declares mp1 as a MarriedPerson. Then it goes and sets its "married" attribute to false. So now, this MarriedPerson is no longer married. So why is it still a MarriedPerson?

As the meme goes: Y U No Makey Sense?!

I have a book by Peter Coad, Eric Lefebvre, and Jeff De Luca called Java Modeling in Color with UML (Prentice Hall, 1999). I don't refer to it often but there's one useful concept from it that I like to employ in cases like this and that's the idea of a "Moment-Interval" archetype. This applies to things that occur at specific moments or intervals in time like a Sale, a Rental, or a Loan. An address can be a Moment-Interval as well. For example, say you lived in a condo for a year, moved away for a few years, then moved back to the same condo. For certain application domains, you could have three addresses which are modeled as separate Moment-Intervals. Other domains might allow you to model that situation as just two separate addresses/moment-intervals. It all depends on the context whether one model or the other is appropriate to use.

As for MaritalStatus, I would say that is a good candidate for a Moment-Interval as well, since it applies to an interval of time in a Person's lifetime.

My advice to OP, since this is supposed to be for "beginner" levels, is to follow the instructions you have been given by your teacher but keep in mind that this is NOT a good example of using polymorphism. Using polymorphism like that to print out different messages is not a very good design. You should not do this kind of thing in a real-world program.
 
Liutauras Vilda
Marshal
Posts: 4657
319
BSD
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Alexandros Stefanidis,

Also doesn't look right to keep MyTester class as an abstract. Maybe you meant to make it final and with private constructor so no one could instantiate it. Revise that part.
That could look similar to:

Also you omitted some curly braces around if statements in printInfo method. I know it is allowed when there is only one statement in it, but probably better not to omit them even then.
Next, same method:I see what you did here, not sure if it is a good approach. Might someone else more experienced will advice on this, but for less confusion i'd go in simple way:
MORE better probably is to write:
 
Campbell Ritchie
Marshal
Posts: 55768
163
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Agree about the ?: operator, though many beginners find that operator hard to understand.
i am not convinced I like the multiple print calls; each takes an appreciable time. I don't know how long, and I don't know whether other code can be executed in parallel with a print instruction, but i do know that I can watch hundreds of lines being printed to System.out, so I suspect each print call takes several milliseconds, as against creating Strings inside the Java® runtime, which probably takes a few μs. That is one reason I suggested a toString method; you can do all the String building in one place and print the result with a single print call. I have seen ?: used like this:-
"... %s ...", ..., isMarried() ? "married" : "not married", ...
You would use the %s tag inside method calls like myFormatter.format(), String#format, System.out.format, System.out.printf, etc. They all work quite similarly to one another.

Another reason for using toString is that it is the “Java® way” to do things. The toString() method is inherited from the Object class, and is therefore in every object you create. Also method calls like System.out.println() assume that toString has been overridden in the objects pass to them. You can write System.out.println(myObject) and get a useful printout if you override toString.
 
Junilu Lacar
Sheriff
Posts: 11165
160
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:Another reason for using toString is that it is the “Java® way” to do things. The toString() method is inherited from the Object class, and is therefore in every object you create. Also method calls like System.out.println() assume that toString has been overridden in the objects pass to them. You can write System.out.println(myObject) and get a useful printout if you override toString.

If you're going to design for inheritance anyway, I might consider doing something like this:

If you want to prevent subclasses from totally changing the behavior of the base toString(), you would make it final in the base class. That way, subclasses would be forced to just use the moreToString() method to extend the behavior of toString(). This is basically the Template pattern.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!