/* MuppetMonster.java example code AC Chapin */ package MonsterInherit; /** * class representing a Muppet Monster * */ public class MuppetMonster extends Monster { private String mySong; // instance var for this class not in Monster private Monster friend; /** * default constructor for MuppetMonster * */ public MuppetMonster() { super("Mup", 0, true); setMySong("La la la la la"); setMyFriend(null); // just being explicit about no infinite recursion } /** * default constructor for MuppetMonster * */ public MuppetMonster(String name, String song) { super(name, 0, true); setMySong(song); } /** * copy constructor for MuppetMonster * */ public MuppetMonster(MuppetMonster original) { // handles copying all Monster stuff super(original); // now just handle muppet-specifics if (original != null) { setMySong(original.mySong); if (original.getFriend() != null) { // we don't know which subclass // so use clone friend = original.friend.clone(); } // otherwise stays null } else { // same as default setMySong("La la la la la"); } } /** * MuppetMonsters eat cookies overrides eat from Monster * */ public void eat() { System.out.println("C is for cookie, and cookie is for me!"); } /** * MuppetMonsters can sing * */ public void sing() { System.out.println("I sing " + getMySong()); } /** * MuppetMonsters don't roar * */ public void roar() { // do nothing } /** * MuppetMonsters don't fight!! * */ public void fight(Monster other) { System.out.println(other + " may fight with " + this + ", but nice MuppetMonsters won't fight back."); } /** * clone method - gives us polymorphic way to call right copy constructor * */ public MuppetMonster clone() { return new MuppetMonster(this); } /** * overrides toString from Monster * * @return string representing this MuppetMonster * */ public String toString() { String friendStatus = "wants"; if (getMyFriend() != null) { friendStatus = "has"; } return super.toString() + " a muppet monster who likes to sing " + getMySong() + " and " + friendStatus + " a friend"; } /** * check if equal to obj * */ public boolean equals(Object obj) { // superclass equals checks for nulls and other vars // if we get that far, check for only other MuppetMonsters if (super.equals(obj) && obj instanceof MuppetMonster) { // cast to get access to vars MuppetMonster mobj = (MuppetMonster)obj; // check own var // taking advantage of short circuit evaluation of && so no null pointer // choosing not to check friend... it could lead to infinite recursion hell return getMySong() != null && getMySong().equals(mobj.getMySong()); } return false; } /* accessors and mutators */ public String getMySong() { return mySong; } public void setMySong(String val) { mySong = val; } // accessor for friend returns a copy // this is safer -- caller gets all the information // but doesn't have direct access to mess up our friend public Monster getFriend() { // clone makes a copy no matter which type friend actually is if (friend != null) { return friend.clone(); } return null; // note that if we did // return new Monster(friend); // then if friend was a subclass (muppet or vampire) // we'd get a base class Monster instead } public void setFriend(Monster friend) { this.friend = friend; // might be safer to instead do //this.friend = friend.clone(); // so our new friend is a copy of the one given // and the original giver doesn't have unsafe access // to mess with our clone } }