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.
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 + '!';
}
}
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.
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).
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);
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);
}
How about combining both:
//Warrior class
public String display()
{
return "This " + description + " warrior uses a "+weapon.display();;
}
//Weapon class
public String display()
{
return name;
}
Related
I have the following interface:
public interface IStaff {
public StaffPosition getPosition();
public String toString();
}
and the class:
public class Worker implements IStaff {
private String name = null;
private String surname = null;
private int age = 0;
//StaffPosition is an enumeration class
private StaffPosition position= null;
public Worker (String name, String surname, int age, StaffPosition position){
this.name = name;
this.surname= surname;
this.age= age;
this.position= position;
}
#Override
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append(this.name);
buffer.append(" ");
buffer.append(this.surname);
return buffer.toString();
}
#Override
public StaffPosition getPosition() {
return this.position;
}
public int getAge(){
return this.age;
}
In another class - Building, I have a HashMap<Office, IStaff> officeswhere Office is a normal class which only holds the number of the office and has a getter for that number.
And then in a yet another class Company I have an ArrayList<Building> buildings, which holds information about all the buildings of a company. In this class I need to get the age of a worker but how can I do that? So far I have a loop like this to get to the map:
for (Building building: buildings) {
for (Map.Entry<Office, IStaff> office: building.offices.entrySet()) {
//get the age of a worker
}
}
Is there a way to do that?
The only real answer is: when you need such an information in places where only your interface should show up, then that information needs to sit on the interface.
So your interface could have a method getAge(), or maybe getBirthday().
Side notes:
using I for "interface" in class names ... is bad practice, or at least: very much against java conventions.
you don't need to have a toString() in your interface. You get one from Object anyway.
(of course, there are dirty tricks, like doing an instanceof check somewhere, and then casting to the type of the concrete class. But as said: that is really bad practice)
Make IStaff an abstract class and then call the method.
I am new to java and learning basic concepts. I was learning abstraction and the most basic definitions i found was : Used to hide the complexity (hide how a process will be done and show what can we do?)
Fair enough. I got a basic idea of what is abstraction. But i am not clear in few things here:
Lets see the below example:
/* File name : Employee.java */
public abstract class Employee {
private String name;
private String address;
private int number;
public Employee(String name, String address, int number) {
System.out.println("Constructing an Employee");
this.name = name;
this.address = address;
this.number = number;
}
public double computePay() {
System.out.println("Inside Employee computePay");
return 0.0;
}
public void mailCheck() {
System.out.println("Mailing a check to " + this.name + " " + this.address);
}
public String toString() {
return name + " " + address + " " + number;
}
public String getName() {
return name;
}
public String getAddress() {
return address;
}
public void setAddress(String newAddress) {
address = newAddress;
}
public int getNumber() {
return number;
}
}
Salary.java
/* File name : Salary.java */
public class Salary extends Employee {
private double salary; // Annual salary
public Salary(String name, String address, int number, double salary) {
super(name, address, number);
setSalary(salary);
}
public void mailCheck() {
System.out.println("Within mailCheck of Salary class ");
System.out.println("Mailing check to " + getName() + " with salary " + salary);
}
public double getSalary() {
return salary;
}
public void setSalary(double newSalary) {
if(newSalary >= 0.0) {
salary = newSalary;
}
}
public double computePay() {
System.out.println("Computing salary pay for " + getName());
return salary/52;
}
}
Main.java
/* File name : AbstractDemo.java */
public class AbstractDemo {
public static void main(String [] args) {
Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00);
Employee e = new Salary("John Adams", "Boston, MA", 2, 2400.00);
System.out.println("Call mailCheck using Salary reference --");
s.mailCheck();
System.out.println("\n Call mailCheck using Employee reference--");
e.mailCheck();
}
}
My question here is , we cant even intsantiate an abstract class. So we have to extend it and overide the same method? When we override the abstract methos in the child class, the super class(abstract class method) is of no use. Also as we cant even intantiate , why cant we just write everything in one class instead of extending the abtsrcat class?
While extending the abstract class and overriding the same thing is it not a negative as the space will more for these waste abstract classes?
I know i dont have clarity and thats the reason i am confused. If anyone can clarify this (no stratight definions which are not useful for noobs like me) with explanation , i would really appreciate the time for that.
Aside of bad example you use, your understanding of Abstract class is not right:
So we have to extend it and overide the same method? When we override the abstract methos in the child class, the super class(abstract class method) is of no use
First: Abstract class and Interface both stay to provide abstract methods to be overridden by extending or implementing classes.
Second: Abstract class can have common methods implementation for all extending classes - then you do not need to implement or override them over and over again. Just use them. (Note: starting from Java 8 Interface also can have default implementation for methods)
Third: if you need another than common implementation - override needed method from super class.
Forth: if in your another implementation you need to run super method - do it at any time in the implementation by calling super.methodName(...)
I started Java a while ago and I am now busy with abstract classes. I've been busy with this code for two days now and I can't find out how to fix this. The methods names might not be in English, sorry for that but I think it wouldn't be too big of a problem.
I don't know why the output is as following:
null null null null
null null null null
null null null null
null null null null
I hope you guys can help me out. I would appreciate any help! Thanks in advance.
Main class, which is also abstract:
public abstract class Boek {
public String isbn;
public String auteur;
public String paginas;
public String titel;
public abstract void setIsbn(String isbn);
public abstract void getIsbn();
public abstract void setAuteur(String auteur);
public abstract void getAuteur();
public abstract void setPaginas(int paginas);
public abstract void getPaginas();
public abstract void setTitel(String titel);
public abstract void getTitel();
public static void main(String[] args) {
Studieboek sb = new Studieboek();
Roman ro = new Roman();
Dichtbundel db = new Dichtbundel();
sb.setAuteur("J.K. Rowling");
sb.setIsbn("547896587412");
sb.setPaginas(251);
sb.setTitel("Harry Potter");
sb.addNAuteur("R.K. Dale");
sb.addOndertitel("Exactly");
sb.printSB();
ro.setAuteur("Suzanne Vermeer");
ro.setIsbn("9632589632574");
ro.setPaginas(311);
ro.setTitel("De Zwarte Piste");
ro.printRO();
db.setAuteur("A.Y. Lmao");
db.setIsbn("5781236985478");
db.setPaginas(171);
db.setTitel("Rijmen kreng");
db.addGedicht("Rijmpje");
db.printDB();
}
}
First subclass:
public class Studieboek extends Boek {
private String ondertitel;
private String nAuteur;
#Override
public void setIsbn(String isbn) {
}
#Override
public void getIsbn() {
}
#Override
public void setAuteur(String auteur) {
}
#Override
public void getAuteur() {
}
#Override
public void setPaginas(int paginas) {
}
#Override
public void getPaginas() {
}
#Override
public void setTitel(String titel) {
}
#Override
public void getTitel() {
}
public void printSB() {
System.out.println(titel + " " + auteur + " " + paginas + " " + isbn + " " + ondertitel + " " + nAuteur);
}
public void addOndertitel(String ondertitel) {
}
public void addNAuteur(String nAuteur) {
}
I have two more subclasses after this but I don't think it is necessary for the code to work, because the code in both other subclasses are exactly the same and give the exact same output.
Again, any help is appreciated. Thanks in advance.
Sincerely,
Double
Your setters aren't doing anything.
A correct way to implement e.g. your setter for isbn would be:
#Override
public void setIsbn(String isbn) {
this.isbn = isbn;
}
Note the part where it actually sets something.
Your getters are equally wrong. A getter should return something, i.e. not be declared as void and have a return statement:
#Override
public String getIsbn() {
return this.isbn;
}
I know they should contain a return value, but the return value gives an error and whenever I leave it empty it seems fine.
(from the comments)
I'm guessing the error is something along "a void method cannot return anything" and yes, it will be fine - unless you try something like
System.out.println(sb.getIsbn()); // Will also print "null"
I'll leave the rest up to you.
Bonus 1: If you have an abstract parent class anyway, you can move the common getters and setters to Boek instead of just declaring them as abstract. This will save you from having to re-implement them in each of your subclasses again.
Bonus 2: public fields (as in public String isbn;) are usually discouraged. You already have the getters and setters, so make them protected (see also: encapsulation).
Bonus 3: As already pointed out by Mike 'Pomax' Kamermans in the comments: You don't want to have your main method in your Boek class. Create a separate "application" class with only the main method to start up your application.
Bonus 4: I believe the standard way of what you want to achieve with your printSB, printRO and printDB methods would be to override the toString() method. Although this might be different for your special use case.
Use it as following:
public class Studieboek extends Boek {
...
#Override
public String toString() {
return this.isbn + " " + this.auteur; // Plus the others
}
}
And
// No need to call an additional method, toString will be invoked automatically
System.out.println(db);
Your set and get methods are empty. You need to set a value in the setters and return the value in the getters.
Right now you are trying to print a variable that has not yet been set - so yes, it is going to print null.
public class FooClass{
private String foo;
public void setFoo(String foo) {
this.foo = foo;
}
public String getFoo() {
return foo;
}
}
You are printing the variable, whose values have not set. You have set the variable values in setter methods in order to print the values. Setter methods to set the values. And getter methods to return the values.
#Override
public void setTitel(String titel) {
this.titel=titel;
}
#Override
public String getTitel() {
return titel;
}
Here is my code
class Bomb {
static String description = "bomb description";
static int id = 1;
private String name;
private int size;
public static void Bomb() {
id++;
System.out.println(" " + description + " " + id);
}
public void setName(String name) {
this.name = name;
}
public void setSize(int size) {
this.size = size;
}
public void printout() {
System.out.println(" " + name + size);
}
}
public class array {
public static void main(String args[]) {
Bomb.Bomb();
Bomb detenator = new Bomb();
Bomb destroyer = new Bomb();
destroyer.setName("hr4");
destroyer.setSize(43);
detenator.setName("m1s");
detenator.setSize(34);
detenator.printout();
destroyer.printout();
}
}
I want the description to print with each bomb object. but the description prints by itself.
any one got any idea how to fix that?
also please suggest any alternative ways I could've written this code, but don't make it to complicated. i just started learning java so i probably wont understand complex stuff.
I short, there are no "static constructors".
You may want something that references a static member, like this:
public Bomb() {
id++;
System.out.println(" " + Bomb.description + " " + id);
}
Please go over the Java tutorial of constructors:
Constructor declarations look like method declarations—except that they use the name of the class and have no return type.
Your definition of constructor is completely messed up.
As #Reut Sharabani mentioned there is no something like static constructor. You are using constructors to initiate object of a class. And static let you use method just by calling ClassName.staticMethod() without creating object of the class (one ruling out another). If static constructor would exist you would be able to write something like, for example, ClassName.ClassName() which make no sense.
Constructors are not returning any value, so declaring them as void is an error. Again constructor is used to initialize your object with some values (but unnecessary)
Once upon modifying the above with static modifiers, line 16 requires the following syntax:
getLegs();toStrung();
//I think this is essentially printing the last called method updating class field variable toString. For example, to do setLegs();toStrung(); prints setLegs()'s toString.
Question: How should one access a shared field within methods? What if I included it into the constructor? Ideally, I want the code to look like getLegs().toStrung() and for toString to be a clean slate for every method.
My answer: I think a seperate instance of String toString inside each method works to get a clean slate appeal, but the syntax doesn't make sense. I know it is about my design. I think a solution would be a new class, but this returns to the same conflict that relates to the class field variable.
public class Dog{
public String toString;
public Dog(String name){
this.name = name;
}
public int getLegs(){
toString = "Dog has " + legs + " legs.";
return legs;
}
public int setLegs(int legs){
toString = getName() + "'s legs have changed from "
+ getLegs() + " to " + legs + ".";
this.legs = legs;
return this.legs;
}
public void toStrung(){
System.out.println(Dog.toString);
}
public static void main(String[] args){
Dog Dundt = new Dog("Dundt");
Dundt.getLegs();
Dundt.toStrung();
}
1) toString() should not be a static member.
2) getLegs() should not have the side effect of changing the member String toString.
3) There should not be a member variable String toString.
4) toString() should return a String.
5) name needs to be a member.
6) legs needs to be a member.
7) toString() should generate the string from the members at run time.
8) You do not need to explicitly call toString() in main. Simply passing the instance of Dog to println will call it for you.
9) It is good practice to annotate methods you are overriding with the #Override annotation. toString() is a member of Object and you are overriding Object.
public class Dog{
private String name;
private int legs = 4;
public Dog(String name){
this.name = name;
}
public int getLegs(){
return legs;
}
public int setLegs(int legs){
this.legs = legs;
return this.legs;
}
#Override
public String toString(){
return "Dog is called " + name + " it has " + legs + " legs.";
}
public static void main(String[] args){
Dog dundt = new Dog("Dundt");
System.out.println(dundt);
}
}