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(...)
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'm doing an assignment for school and im implementing a super but its not working yet i feel its done right. anyone have any idea why my super gives me a syntax error. It tells me "The Constructor Employee(String, String, String) is undefined yet it is though.
Here's my employee class that my other classes extend off of which have this super error.
/**
* Abstract class Employee - write a description of the class here
*
* #author (your name here)
* #version (version number or date here)
*/
public abstract class Employee
{
private String firstName;
private String lastName;
private String socialSecurityNumber;
public Employee(String first, String last, String ssn)
{
firstName=first;
lastName=last;
socialSecurityNumber=ssn;
}
public abstract double earnings();
public String toString()
{
return("\n"+firstName+" "+lastName+
"\nsocial security number: "+ socialSecurityNumber);
}
}
Here's one class with the super that gives me the issue.
public class SalariedEmployee extends Employee{
private double weeklySalary;
// four-argument constructor
public SalariedEmployee(String first, String last, String ssn, double salary) {
super(first, last, ssn); // pass to Employee constructor
setWeeklySalary(salary); // validate and store salary
} // end four-argument SalariedEmployee constructor
// set salary
public void setWeeklySalary(double salary) {
weeklySalary = salary < 0.0 ? 0.0 : salary;
} // end method setWeeklySalary
// return salary
public double getWeeklySalary() {
return weeklySalary;
} // end method getWeeklySalary
// calculate earnings; override abstract method earnings in Employee
public double earnings() {
return getWeeklySalary();
} // end method earnings
// return String representation of SalariedEmployee object
public String toString() {
return String.format("salaried employee: %s\n%s: $%,.2f",
super.toString(), "weekly salary", getWeeklySalary());
} // end method toString
} // end class SalariedEmployee
My other two classes like i said have the same issue so i don't think it would be necessary to post them but any help is greatly appreciated!
That may happens if you have another Employee class defined somewhere else in your project (could be in one of your .java file in the same package, some imports or in the classpath).
Your call to super(first, last, ssn) is all good. You may try to compile the two files in command line to confirm the above:
javac Employee.java SalariedEmployee.java
I try to run a programm but i get those four errors.
TestCusomer.java:25: error: toString() in Invoice cannot override toString() in Object (same thing at line 49)
and
line 59 cannot find symbol . myCustomer.setTrn(112233778)
line 60 cannot find symbol . myCustomer.setPersentage(150)
My programm is the following:
class Invoice
{
int trn; //TAX REGISTRATION NUMBER
int persentage;
public Invoice{}
public int setTrn(int trn){
this.trn = trn;
}
public int getTrn(){
return trn;
}
public void setPersentage(int persentage){
this.persentage = persentage;
}
public int getPersentage(){
return persentage;
}
String toString(){
System.out.println(trn+" : "+persentage);
}
}
class Customer{
int trn;
int charging= 0;
public Customer(int trn){
this.trn = trn;
}
public int charge(int amount){
charging = charging + amount;
}
public int charge(int amount , int trn){
if (this.trn == trn){
charging = charging + amount;
}
}
String toString(){
System.out.println(trn+" : "+charging);
}
}
class TestCustomer
{
public static void main(String[] args){
Customer myCustomer = new Customer(112233778);
myCustomer.charge(100);
myCustomer.setTrn(112233778);
myCustomer.setPersentage(150);
System.out.println(myCustomer);
}
}
few things,
You need to declare the toString method public
You need to return a String in your toString methods
I strongly suggest you add the #Override notation when you override a method to ensure that you actually override the method
The cannot find symbol... happen because those methods are not defined in Customer, you have those in Invoice
Your toString() methods need to return String objects. You are outputting a string in them but not returning a string. Also make them public.
For example, your toString() method for the Invoice class should be:
public String toString()
{
return trn + " : " + persentage;
}
And for your second problem (cannot find symbols), those methods are in the Invoice class and not in the Customer class so they cannot be called on a Customer object.
id appreciate anyones help here. Below is my class that contains all my setters and getters, in my main class, ive created 3 customers and in the value parameters, i have 3 different numbers. What i need to do is find the total value of all of those values, is there any way that i can create a method (See bookingValue below) that will calculate and add the the total of each customers value parameter? Bare in mind that 3 is not a fixed number, so the method should not be affected should i choose to add in more customers. This is probably really basic but if someone could get me on the right path, that'd be great, cheers
public class Customer
{
private int identity;
private String name;
private String address;
private double value;
public Customer()
{
identity = 0;
name = "";
address = "";
value = 0.0;
}
public void setIdentity(int identityParam)
{
identity = identityParam;
}
public int getIdentity()
{
return identity;
}
public void setName(String nameParam)
{
name = nameParam;
}
public String getName()
{
return name;
}
public void setAddress(String addressParam)
{
address = addressParam;
}
public String getAddress()
{
return address;
}
public void setValue(double valueParam)
{
value = valueParam;
}
public double getCarCost()
{
return value;
}
public void printCustomerDetails()
{
System.out.println("The identity of the customer is: " + identity);
System.out.println("The name of the customer is: " + name);
System.out.println("The address of the customer is: " + address);
System.out.println("The value of the customers car is: " + value + "\n");
}
public void bookingValue()
{
//Ive tried messing around with a for loop here but i cant seem to get it working
}
}
you can create an array of object of class customer and access the value in loop...
In the main function:
customer cus[]=new customer[num];
where num can be any number as 3 in your case
then get the "value" for each customer.. and then
public double bookingValue(customer []cus, int length)
{
double total=0.0;
for(int i=0;i<length;i++)
total+=a[i].value;
return total;
}'
return total value wherever you want to use.....
As in real life, one customer doesn't know anything about the other customers. If you would ask a customer in a store how much all customers spent, he will just look as confused as others reading this question.
I'd suggest implementing some CustomerManager, or Bookkeeper which hold all the customers internally (in a List for example). This CustomerManager needs to have methods to add and remove customers, the getBookingValue() method which loops over all customers in the CustomerManager's customers List and returns the total value and, if you please, some other comfort methods.
As an example:
public interface CustomerManager {
public void addCustomer(Customer customer);
public void removeCustomer(Customer customer);
public List<Customer> getCustomersByDate(long from, long to);
public double getBookingValue();
public double getBookingValue(List<Customer> customerList);
public List<Customer> getByAddress(String address);
public List<Customer> getByName(String name);
}
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;
}