Just started learning java recently, and in my textbook I came across this which was very confusing at first but now its starting to make sense. Now, in my book we
started basic applications of constructors and as a side note on the page it said this, can also be used to call other constructors. I was a bit confused, then
look at other questions on SO regarding this. I think I get it to an extent now, but WHY would I ever want to do this? Consider the following which I just made up.
private double balance;
private double interest;
public Account(double initialBalance){
balance = initialBalance;
}
public Account(double balance, double interest){
this(0);
balance = initialBalance;
this.interest = interest;
}
Here this(0);, to my understanding looks for another constructor with one parameter, finds Account(double initialBalance), and sets initialBalance to zero.
Great. Erm, but why wouldn't I just do that directly? Just set balance equal to zero! I am sure it is very useful but I can't think of any examples.
Thanks!
It's very practical and avoids code duplication:
public Account(){
this(0);
}
public Account(double initialBalance){
this(initialBalance, DEFAULT_INTEREST_RATE);
}
public Account(double balance, double interest){
balance = initialBalance;
this.interest = interest;
}
The constructors with less arguments delegate to constructors with more arguments, passing defaults for the absent arguments.
If this weren't possible, one would need an artificial init(..) method which accepts the parameters, and is called from all constrcutors. This is less secure, as this method could be called repeatedly.
The example from Java documentation will probably make much more sense than the one you have at your hands:
public class Rectangle {
private int x, y;
private int width, height;
public Rectangle() {
this(0, 0, 1, 1);
}
public Rectangle(int width, int height) {
this(0, 0, width, height);
}
public Rectangle(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
...
}
Think about that you could do it the other way: Your "basic" constructor is
public Account(double balance, double interest){
balance = initialBalance;
this.interest = interest;
}
and based on this, you could add some simplifications:
public Account(double initialBalance){
this(initialBalance, DEFAULT_INTEREST);
}
public Account(){
this(DEFAULT_INITIAL_BALANCE, DEFAULT_INTEREST);
}
Calling these constructors simplifies changing the principal behaviour: if I, e. g., want to register the new object somewhere, I can do so at one central place and have the other constructors rely on that.
Here's a good example to use another constructor of the same Object:
public Person(String name, String street, String location) {
(...)
//handle them
}
public Person() {
this("default name", "default street", "default location");
}
It's basically a shortcut (Overloading), so you stay clear of redundant code.
Overloading constructors may come in handy many times.
One example is when you have multiple arguments but not all of the are mandatory.
Using overloading you can do something like:
public Account(string id, double balance, string name, strings address){
this.id = id;
this.balance = balance;
this.name = name;
this.address = address;
}
public Account(string id, double balance, string name){
this(id, balance, name, null);
}
public Account(string id, double balance){
this(id, balance, "Unknown" ,null);
}
public Account(string id){
this(id, 0, "Unknown" ,null);
}
That example does indeed make not much sense.
The following does.
private double balance;
private double interest;
public Account(double initialBalance){
this(initialBalance, 9.99);
}
public Account(double balance, double interest){
this.balance = balance;
this.interest = interest;
}
And indeed one calls another constructor, that typically does some work than just assigning.
For the original example it could be that the simple constructor was made first, and later the constructor with the extra argument was added for an extra field interest.
So one might see this construct often, and it is comparable with calls to super(...)
Also in simple cases, this usage follows the DRY principle: Don't Repeat Yourself. Mind if one of the constructor had just a bit different couple of assignments in time, the program would become constructor case dependent. Now you know, that the same code is walked through, and you do not have to test that functionality N times.
This is called "constructor overloading". Just like method overloading, this is Java's way of allowing you to supply different amounts of parameters for a single method.
It is generally used for methods, or in this case, constructors that have "optional" parameters. Heres an example that should make it more obvious:
class Cat{
private int paws;
private String name;
public Cat(String name){
//Assume that the cat is physically not handicapped, and thus has 4 paws
this(name,4);
}
public Cat(String name, int paws){
this.name = name;
this.paws = paws;
}
}
It would make more sense if you put it the other way around.
public Account(double initialBalance){
this(initialBalance, 2.0); // 2.0 being a default interest (whatever you'd like, could be 0).
}
public Account(double balance, double interest){
this.balance = balance;
this.interest = interest;
// Some more very difficult business logic
}
This way you can prevent duplicate code. A change in the difficult business logic would only have to be changed once (if needed).
Related
edit: added employee constructors;
my question involves constructor chaining for a subclass (to a super which is itself a subclass). I have written constructors that seem to work, but I feel that they are incorrectly written as I will explain. PTEmployee extends to Employee who is extended to a Person. The code below seems to work in my test class,
public class PartTimeEmployee extends Employee {
public static final int DEFAULT_HOURSPRWK = 0;
private int hoursPerWk;
public PartTimeEmployee() {
this(DEFAULT_HOURSPRWK);
}
public PartTimeEmployee(int hoursPerWk) {
this(DEFAULT_HIRE_DATE, DEFAULT_INCOME, hoursPerWk);
}
public PartTimeEmployee(String hireDate, double incomeWk, int hoursPerWk) {
super(hireDate, incomeWk);
this.hoursPerWk = hoursPerWk; // I dont think I need two this.var?
}
public PartTimeEmployee(String firstName, String surname, int age, Address address, String hireDate, double incomeWk, int hoursPerWk) {
super(firstName, surname, age, address, hireDate, incomeWk);
this.hoursPerWk = hoursPerWk;
}
But I feel that the use of two constructors with (super) and this.hoursPerWk = hoursPerWk is wrong, shouldn't '(super)' and 'this.var = var' only need to be written once? If I adjust the code to remove the PTEmp(hiredate, incomewk, hrswk) constructor than I get a 'no constructor found' error in my second constructor. Other edits have led to recursor errors.
So the supplied code works and calls all details in my test class, but is it correctly written (I need to have a Person class that is extended by Employee which is extended by PTEmp or Boss etc.). Appreciate any feedback (or jsut to know this is correct if it is.
Thanks.
Added Employee constructors here...
public class Employee extends Person {
public static final String DEFAULT_HIRE_DATE = "00/00/00";
public static final double DEFAULT_INCOME = 0;
private String hireDate;
private double incomeWk;
public Employee() {
this(DEFAULT_HIRE_DATE, DEFAULT_INCOME);
}
public Employee(String hireDate, double incomeWk) {
this(DEFAULT_FIRSTNAME, DEFAULT_SURNAME, DEFAULT_AGE, new Address(), hireDate, incomeWk);
}
public Employee(String firstName, String surname, int age, Address address, String hireDate, double incomeWk) {
super(firstName, surname, age, address);
this.hireDate = hireDate;
this.incomeWk = incomeWk;
}
Not sure what super() does if you don't specify names, address, etc, but assuming that you can use some defaults, maybe you can call it like this:
public PartTimeEmployee(String hireDate, double incomeWk, int hoursPerWk) {
this(DEFAULT_FIRST_NAME, DEFAULT_SURNAME, DEFAULT_AGE, DEFAULT_ADDRESS, hireDate, incomeWk, hoursPerWk);
}
Consider using builder patterns, if you think that you have too many overloaded constructors:
When would you use the Builder Pattern?
I am having trouble returning my static private variable personCount. This variable simply counts the amount of people i add into my program, in my constructor for Person i set it so every time a person was entered, personCount incremented by 1. I have also created a getPersonCount method which simply returns the int value of personCount.
My problem is that when trying to implement this method in my test file, I am unsure on how to call the method, and get the value of personCount logged to the output.
I'm not sure if i am a million miles away or a small syntax error away, so any help would be much appreciated!
My Person constructor:
public Person(String foreName, String surName, int age,
double height, String gender)
{
this.foreName = foreName;
this.surName = surName;
this.age = age;
this.height = height;
this.gender = gender;
personCount = personCount +1;
}
My getPersonCount method:
public int getPersonCount()
{
return personCount;
}
My attempt to call the method in my test drive:
System.out.println(getPersonCount());
Please let me know if any more code is needed.
Try this, make your method definition in class Person like:
public static int getPersonCount() { //<-- note the static modifier
return personCount;
}
To invoke it:
System.out.println(Person.getPersonCount());//<-- use class name, if your using this method outside the class
You have two choices:
public static int getPersonCount() {
return personCount;
}
with the corresponding call:
Person.getPersonCount();
OR:
public int getPersonCount() {
return personCount;
}
and the corresponding call:
myPersonInstance.getPersonCount();
So in the last case, you deal with a Person instance.
public static int getPersonCount(){
return personCount;
}
Then invoke above method
Person.getPersonCount();
I am working with a function that takes a class type as parameter:
I am trying to pass getSpans() the specific subclass of the Object "type."
Spannable ss;
Object type;
int start;
int end;
//Assume above variables properly initialized.
....
//getSpans(int start, int end, Class<T> type)
ss.getSpans(start, end, ???);
Yes, just use type.class. It will return the Class object of the type variable. Also try type.getClass().class.
http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html
Better use the 2nd example.
You can achieve this functionality without resorting to a series of instanceof's by using the Strategy Pattern. Here is an example implementation that calculates shipping costs using different providers without actually having to know what provider type is used.
public enum ShippingMethod {
FIRST_CLASS {
public double getShippingCost(double weightInPounds, double distanceInMiles) {
// Calculate the shipping cost based on USPS First class mail table
}
},
FED_EX {
public double getShippingCost(double weightInPounds, double distanceInMiles) {
// Calculate the shipping cost based on FedEx shipping
}
},
UPS {
public double getShippingCost(double weightInPounds, double distanceInMiles) {
// Calculate the shipping cost based on UPS table
}
};
public abstract double getShippingCost(double weightInPounds, double distanceInMiles);
};
public class ShippingInfo {
private Address address;
private ShippingMethod shippingMethod = ShippingMethod.FIRST_CLASS;
public Address getAddress() {
return this.address;
}
public double getShippingCost(double weightInPounds, double distanceInMiles) {
return shippingMethod.getShippingCost(weightInPounds, distanceInMiles);
}
}
More info on the Strategy Pattern and full example.
I'm trying to understand Inheritance a little better but I can't seem to get it to work. I'm creating a base object for a pizza. A base, deep pan or thin. I have 2 classes, Pizza, PizzaBase. I'm keeping the private variables in Pizza, and trying to call them when building my pizzabase. Here's my 2 classes. But its not working. I get the message setCost(double) is undefined for the type Pizza
You code is wrong in every way.
Listen to the compiler: if it says you can't call setCost() on Pizza because there is no such method, it means you didn't define it.
You ought to do something more like this:
public class Pizza {
private double cost; // double is NOT a good idea for money
public Pizza(double cost) {
if (cost < 0.0) throw new IllegalArgumentException("we won't pay you to take our pizza!");
this.cost = cost;
}
public double getCost() { return this.cost; }
}
public class ThinPizza extends Pizza {
private static final double DEFAULT_COST = 2.0;
public ThinPizza() { this(DEFAULT_COST); }
public ThinPizza(double cost) { super(cost); }
}
public class ThickPizza extends Pizza {
private static final double DEFAULT_COST = 5.0;
public ThickPizza() { this(DEFAULT_COST); }
public ThickPizza(double cost) { super(cost); }
}
You can call getCost() on thin and thick pizza, because it IS-A Pizza.
I have been experimenting with Classes in Java over the last few days, learning about them from "TheNewBoston" on youtube and from the java docs.
I have created the following scenario and seek your guys' (girls too) professional criticism and in depth knowledge regarding a few questions I have.
There are two classes, person and person_financial, a base class and sub class respectively.
person class:
public class person {
private String name;
private String sex;
private int age;
private double height;
private double weight;
private double intelligence;
// person constructor arguments order: name, height, weight, age, sex, intelligence
public person(){
this("noname",0,0,0,"undefined",5);
}
public person(String n){
this(n,0,0,0,"undefined",5);
}
public person(String n, double h){
this(n,h,0,0,"undefined",5);
}
public person(String n, double h, double w){
this(n,h,w,0,"undefined",5);
}
public person(String n, double h, double w, int a){
this(n,h,w,a,"undefined",5);
}
public person(String n, double h, double w, int a, String s){
this(n, h, w, a, filterSex(s), 5);
}
public person(String n, double h, double w, int a, String s, double i){
name = n;
height = h;
weight = w;
age = a;
sex = filterSex(s);
intelligence = i;
}
public void setName(String n){
name = n;
}
public void setHeight(double h){
height = h;
}
public void setWeight(double w){
weight = w;
}
public void setAge(int a){
age = a;
}
public void setSex(String s){
sex = filterSex(s);
}
public void setIntel(double i){
intelligence = i;
}
public String getName(){
return name;
}
public double getHeight(){
return height;
}
public double getWeight(){
return weight;
}
public int getAge(){
return age;
}
public String getSex(){
return sex;
}
public double getIntel(){
return intelligence;
}
public String getInfo(){
return String.format("Name: %s,\nSex: %s,\nAge: %d,\nIntelligence: %.2f,"
+ "\nHeight: %.2f,\nWeight: %.2f\n", name, sex, age,
intelligence, height, weight);
}
private static String filterSex(String s){
return ((s.equalsIgnoreCase("male") ||
s.equalsIgnoreCase("female")) ? s : "undefined");
}
}
person_financial class:
public class person_financial extends person {
private double monies = 0;
public void definePerson(String n, int a, String s, double i, double h, double w){
setName(n);
setAge(a);
setSex(s);
setIntel(i);
setHeight(h);
setWeight(w);
}
public person_financial() {
this(0);
}
public person_financial(double m) {
monies = m;
}
public void depositMonies(double m) {
monies += m;
}
public void withdrawlMonies(double m) {
if (m <= monies) {
monies -= m;
}
}
public double getBalance() {
return monies;
}
}
and then in the main class I have this:
public class Main {
public static void main(String[] args) {
person p1 = new person("I have no Name", 180, 72, 38, "Alien", 7.2);
System.out.println(p1.getName());
person_financial pf1 = new person_financial(100.00);
pf1.depositMonies(50.02);
System.out.printf("%s has %.2f monies.\n", pf1.getName(), pf1.getBalance());
pf1.definePerson("some_name", 42, "male", 10, 180, 72);
System.out.println(pf1.getInfo());
}
}
in the person_financial class, I have made a method called "definePerson()" which I use to define all the characteristics that would otherwise have been defined from the 'person()' constructor from the 'person' class. I'm sure there is a more professional way for assigning values to variables in a base class from a sub class, I just dont know of any...
Also, is there any way to call the constructor from the "person" class to define characteristics for 'pf1'? rather than having to, for example, manually set each attribute, i.e. pf1.setName("something"); , or pf1.setAge(1000000); etc... or have a method do it for me, as in 'definePerson()'.
Any help is much appreciated,
Thanks =).
You use the super() call to call the constructor of the parent class. It has to be the first call in the constructor of the derived class, but you call it (and pass in arguments) like any other function and it will call the constructor that way.
It's common to declare a class 'abstract' to prevent creation of generic objects - based on your usage-code at the bottom you seem not to want that and that's fine. Just remember that you can declare declare a class abstract.
The best way to use class hierarchy is to ensure that (buzzword alert) any class in a useful hierarchy should be declarable as anythin in the hierarchy (i.e. you should be able to access any methods in your concrete object from the base-class (person in this case).
Your financial_person object extends person, but the ideal is to have a class that you can declare at a high level and call methods polymorphically. Consider for a minute that all people are able to draw and deposit money (different from your classes, but bear with me for a minute).
drawMoney method would exist in person, but be marked abstract - forcing the subclasses financial_person and regular_person to implement draw_money, deposit_money etc.
each class would have an implementation that suits their reality (financial person would have access to all kinds of special accounts, discounts etc., and regular_person would have a simpler set of - but still the same external behavior).
Then you could declare like this:
Person finPerson = new FinancialPerson(... etc.);
Person regPerson = new RegularPerson(....etc);
note now that you are able to do this code below:
finPerson.drawCash(12300.0);
regperson.drawCase(100.0);
The identical behavior.
You could have a List of thousands of people, and would not have to do if-then-else or switch statements to execute the finer-tuned behaviors of each.
The acid-test for class-hierarchy is this: "my (sub-class) really 'a kind of' (superclass)?"
In other words, "does my subclass have behaviors of the superclass?"
If not, you should think carefully about class hierarchy. There's a buzzword for this : Liskov Substitution Principle, and I cannot do a better job of this than Robert. C. Martin - one of the software-design gurus:
http://www.objectmentor.com/resources/articles/lsp.pdf
In this article he shows what happens when you have inadvisable hierarchy, using the "a square is a kind-of rectangle" example.
Google "template method pattern" for a summary of another aspect of effectively using inheritance. You will see that it is much more powerful than the simple inheritance that most people dismiss it as being.
Also remember that no single pattern is a silver-bullet for everything. Some people will call class-hierarchy evil and tell you to use interfaces only; others will say the reverse. There are choices to make, and sometimes they will not be obvious.
There are many pitfalls, and missing LSP is just one of them. Others are (examples only) overriding concrete methods, having concrete classes not marked final, enabling mutability of "identifying" fields (eg fields used in equals/hashcode, etc.) Imagine if "customer" objects at bank allowed resetting of first-name, or account-number at runtime, once these fields were already set).
My answer is more generally related to OO design, inheritance etc. than specific coding questions - hope it's of some use to you.