3

I want to print a description of a warrior to the console that will include the warrior's strength and the warrior's weapon in the form This <description> warrior uses a <weapon> For example: This strong warrior uses a butter knife.

Edit for clarity: I want to do this without asking objects for data by using getters or any other method (like toString) which reveals the internal implementation of an object. I also want to do this without hard coding my current UI (a console) into the objects themselves.

public class Warrior
{
  private String description;
  private Weapon weapon;

  public Room(String description, Weapon weapon)
  {
    this.description = description;
    this.weapon = weapon
  }
}

public class Weapon
{
  private String name;

  public Weapon(String name)
  {
    this.name = name;
  }
}

Avoiding Getters

I can avoid getters by hard coding the UI:

//Warrior class
public void display() 
{
  String.out.println("This " + description + " warrior uses a ");
  weapon.display();
}

//Weapon class
public void display() 
{
  String.out.print(name);
}

Avoiding hard coded UI

I can avoid a hard coded UI by using getters:

//Warrior class
public String getDescription() 
{
  return "This " + description + " warrior uses a " + weapon.getName();
}

//Weapon class
public String getName() 
{
  return name;
}

Is it possible to avoid both? How can I do so in the above example?

Note: In response to some initial answers, a getter is not a method that follows the naming convention getSomeFieldName. Therefore, renaming getSomeFieldName to aMethodThatIsNotPrefixedByGet is not a solution. A getter is a method that passes private data from an object to the scope which called it.

To be completely clear, the issue I am trying to deal with here is to do with data encapsulation (as this question is tagged). How can I prevent passing data to objects which do not need to know that data and still avoid hard coding the UI?

Additionally, based on these questions, I don't think toString should be used in the way that it has been suggested by the many of the answers. toString seems to be for generating a text representation of an object for debugging and so forth, not for returning arbitrary output and especially not for returning application dependent output.

Community
  • 1
  • 1
Rupert Madden-Abbott
  • 12,899
  • 14
  • 59
  • 74
  • other that overriding toSting() there is no real way of getting a description of an object in java not using getters - thats wat they are for. Compared with dynamic property access they might seem combersome, admitted – kostja Apr 11 '11 at 06:47
  • @kostja Thanks for your comment! I agree that there is no way of getting a description of an object other than using getters. However, I do not want to "get a description of an object". I want to see if it is possible to tell an object to display its description without hard coding the UI. – Rupert Madden-Abbott Apr 11 '11 at 07:06
  • as you probably have noticed seen your question *getters* are the anti-thesis of OO. There's been a nice thought-provoking article/blog by some famous coder about this (don't remember which one that said). What is important, of course, is how object interacts with each other. If they interact using getters, then it's not OO. People using and overusing getters simply don't get OO. You can't really avoid "hard-coding the UI" if you want your progam to be "OO" for a very simple reason: in a well-designed OO program an object knows how to draw itself. – SyntaxT3rr0r Apr 11 '11 at 08:51
  • but of course you can have your object knowing how to draw itself depending on the objects he's interacting with. For example in a game you may have your object knowing how to send its own drawing orders to your main drawing pipeline and also know how to draw itself on, say, a tiny "mini-map" and also on, say, a text console. It's all about how the object is interacting with other objects and, when it's OO, then there's no arguing: the object **SHOULD** know how to draw itself. – SyntaxT3rr0r Apr 11 '11 at 08:54
  • imagine you have a method *displayMeUsingLanguageAndColorScheme(lang,scheme)*... This is a bit far-fetched, but that's the idea: how hardcoded is *that*? Well, not much, you can still adapt your "hardcoded UI" to the surrounding objects (language, color scheme, etc.). – SyntaxT3rr0r Apr 11 '11 at 08:59

6 Answers6

3

Yes go for i18n,

messages.properties
displayMessage = This {0} warrior uses a {1}

messages.properties_en_US
displayMessage = This {0} warrior uses a {1}

and

public static String getString(String key, Object... params  ) {
        try {
            return MessageFormat.format(RESOURCE_BUNDLE.getString(key), params);
        } catch (MissingResourceException e) {
            return '!' + key + '!';
        }
}
jmj
  • 237,923
  • 42
  • 401
  • 438
1

YOu can override toString in your Warrior class to achieve it.

public String toString() {


return "This " + this.description + " warrior uses a " + weapon.toString();

}

override toString inWeapon to return the name;

as

public String toString() {

    return this.name;

    }

and you can directly print as

System.out.println(warrior);
GuruKulki
  • 25,776
  • 50
  • 140
  • 201
1

I would override the method toString() in both the Warrior and the Weapon, as this method naturally returns a String represenation of an object. Then I would create a class dedicated to creating the descriptions, for example a DescriptionMaker, and create a method in it:

String createDescription(Warrior warrior, Weapon weapon)
{
    return "This " + warrior + " uses a " + weapon;
}

The return value of this method could then be printed to the console. Also, internalization could be applied in the DescriptionMaker class.

janhink
  • 4,943
  • 3
  • 29
  • 37
1

In that case getters seem a good practice to me as they permit you to have your data (Warrior and Weapon classes) separate from your UI (that calls the getters and create the description strings, widgets, html code, etc.). However I wouldn't let the Warrior getter create the string, it would just return the warrior description and the UI class would create the string (what the Warrior.getDescription() method you propose do in you sample).

Guillaume
  • 5,535
  • 1
  • 24
  • 30
1
public Interface IWarriorView {
  public void display(String description, Weapon weapon);
}

public Interface IWeaponView {
  public void display(String name);
}

public class WeaponViewImpl {
  public void display(String name) {
    System.out.println(name);
  }
}

public class WarriorViewImpl {
  public void display(String description, Weapon weapon) {
    System.out.println("This " + description + " warrior uses a ");
    weapon.display(new WeaponImpl());
  }
}

// Warrior class
public String display(IWarriorView view) {
  view.display(description, weapon);
}

// Weapon class
public String display(IWeaponView view) {
  view.display(name);
}
Byeon
  • 11
  • 1
0

How about combining both:

//Warrior class
public String display() 
{
  return "This " + description + " warrior uses a "+weapon.display();;

}

//Weapon class
public String display() 
{
  return name;
}
Harry Joy
  • 58,650
  • 30
  • 162
  • 207