0

Today I came across composition. From what I understand, for each instance of composition I need to create new object in constructor, like this :

public class Human {
   private String name;
   private Adress adress;

   public Human (String name, Adress adress) {
      this.name = name;
      this.adress = new Adress(adress);
   }
}

So if I would create a new instance of class human, I would need to assign to it some instance of adress, or create completely new adress, and the constructor would look like this

public class Human {
   private String name;
   private Adress adress;

   public Human (String name, String city, String country) {
      this.name = name;
      this.adress = new Adress(city, country);
   }
}

First of all, are those codes correct? And also is there any option, that if I would create new instance of class human, the atribute Adress would be empty, and I could set it later by using set method? Thank you very much for your response.

davmac
  • 20,150
  • 1
  • 40
  • 68
D.Walker
  • 15
  • 1
  • 3

6 Answers6

0

A new object is not mandatory in general, however, if you want to have the adress of human immutable (only if Adress is already not immutable), it is a good practice to kill all the references to it from outside the object.

That's indeed the rule for a composition.

This is naturally the way to do it, if adress takes an adress as input within its constructor.

public class Human {
    private String name;
    private Adress adress;

    public Human (String name, Adress adress) {
        this.name = name;
        this.adress = new Adress(adress); 
    }
}

If you want, you could have a set of different constructors and set some of the fields later

public class Human {
    private String name;
    private Adress adress;

    public Human() {}
    public Human(String name){
        this.name = name;
    }
    public Human(String name, Adress adress) {
        this.name = name;
        this.adress = adress; // or new Adress(adress)
    }

    public void setAdress (Adress adress) {
        this.adress = adress;
    }
}
Yassin Hajaj
  • 21,337
  • 9
  • 51
  • 89
  • 1
    Only if `Adress` is not immutable. Otherwise there is no need to copy it. – Andy Turner Mar 13 '16 at 14:03
  • I should protest the fact that your second half of the answer is *copied* directly from mine... – Idos Mar 13 '16 at 14:07
  • @Idos Not at all. I swear on my SO reputation. – Yassin Hajaj Mar 13 '16 at 14:13
  • @YassinHajaj Thank you very much for your response. It clears it out for me, but could you please tell me, if a new object is not a mandatory, would there be just this.adress = adress; ? Wouldn't that be aggregation instead of composition? I thought that aggregation has a reference, and composition needs to create a new instance in constructor. – D.Walker Mar 13 '16 at 14:22
  • @D.Walker You're right. Composition means that if the object is deleted, the composites are also deleted so we need its own object reference. – Yassin Hajaj Mar 13 '16 at 14:25
  • @YassinHajaj so outside of class human, I would somewhere have instance of class Adress. For example adress1. Constructor would create it in form this.adress = new Adress(adress1); . And if we would delete class human, with adress1. The only thing that would be destroyed is that "copy of an instance". but not instance adress1 itself ? – D.Walker Mar 13 '16 at 14:29
  • @D.Walker Yes, Since it has been created oustide. What you may do is, like in your example, accept a constructor with the composition of `Adress` and create your object within the constructor. – Yassin Hajaj Mar 13 '16 at 14:30
0

If I understand you problem correctly then you are looking for a default constructor and getter-setters for Name and Address.

Here is the code snippet:

public class Human {

    private String name; 
    private Address address;

    /* Default Constructor */
    public Human() {}

    public Human(String name, Address address) {
        this.name = name;
        this.address = new Address(address); 
    }

    /* Getter for Name */
    public String getName() {
        return this.name;
    }

    /* Setter for Name */
    public void setName(String name) {
        return this.name = name;
    }

    /* Getter for Address */
    public Address getAddress() {
        return this.address;
    }

    /* Setter for Address */
    public void setAddress(Address address) {
        return this.address = address;
    }
}

Now, you can easily make a new object of class Human by doing this:

Human h = new Human();

And later set the Name or Address as follows:

h.setName("foo");
h.setAddress(new Address("foo","bar"));

Please note that I have fixed the typo in adress.

user2004685
  • 9,548
  • 5
  • 37
  • 54
0

Both of them are correct.

Hovever I prefer the first one, because you work exactly with your class Address that is included in the Human class either.

public class Human {
    private String name;
    private Adress adress;

    public Human (String name, Adress adress) {
        this.name = name;
    this.adress = new Adress(adress); 
    }
}
Nikolas Charalambidis
  • 40,893
  • 16
  • 117
  • 183
0

First of all, are those codes correct?

What do you mean by correct? Does it compile for you? If so then they are (not really, but in that sense at least).

is there any option, that if I would create new instance of class human, the attribute Address would be empty, and I could set it later by using set method?

Yes, you can achieve this in many ways, one of them is by adding an appropriate constructor:

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

And adding a setter:

private void setAddress(Adress adress) {    
    this.adress = adress;    
}
Idos
  • 15,053
  • 14
  • 60
  • 75
  • "_Does it compile for you? If so then they are._" - awesome. This theory almost never works for me... – Boris the Spider Mar 13 '16 at 14:04
  • 1
    Trying to emphasize that the phrase *are those codes correct* is not only grammatically incorrect, but meaningless in general. – Idos Mar 13 '16 at 14:04
0

You could create a new Human object with Address parameters set to null:

Human human = new Human("My Name", null, null);

But then you would have to check these parameters and set address to null if both (or one of) them are null.

Or you could define a new constructor in Human class:

public Human(String name) {
    this.name = name;
    /* The line below is not required, since objects are set to null by default*/
    this.address = null;
}

And you can create a setter method that allows address change only if address is null itself, or the address parameters are null. That is, if that's what you want.
Here's an example below:

public void setAddress(Address address) {
    if (this.address == null) {
        this.address = address;
    }
}
bobasti
  • 1,778
  • 1
  • 20
  • 28
0

Address usually has much more than this: street 1, street 2, city, state, county, postal code, postal code extension, country, lat/lon, etc. I would consider your example inadequate.

An object should be 100% ready to go when it's constructed. You can overload constructors or provide a builder to make that convenient.

One exception to this rule is JSON serialization with Jackson. It requires a no-arg constructor and getter/setter pairs for all serialized private data members, because it uses reflection and Java Bean conventions.

There's no right or wrong, correct or incorrect. There's what works for your code while still promoting readability, clarity, ease of use and change, and maintaining DRY.

One more bit of advice: Names matter a great deal. Think long and hard about them. Human? Really? Unless you intend to have non-Human alternatives, I'd say that Person or Individual or Customer or something for your context would be a better choice.

Here's another: Can a Person have more than one Address? Residence, Mailing, Shipping, Garaging, etc.? How will you handle this?

duffymo
  • 305,152
  • 44
  • 369
  • 561