Interfaces and aggregation

M

Markos Charatzas

Hello to all,

Suppose we have a class Ship and a class Cabin.

Both of these classes support a common interface, say Query and Cabin is
part of Ship. Therefore,

class Ship implements Query
{
String name;
Cabin cabin;

public String getQuery()
{
}
}


class Cabin implements Query
{

public String getQuery()
{
}
}

Now, inside cabin.getQuery() I need to know the ship.name value.
What's the best approach to achieve this? Should I pass a reference of
Ship in Cabin once a cabin object is created? Any other possible way?

Thanks in advance,
Markos Charatzas
 
B

BarryNL

Markos said:
Hello to all,

Suppose we have a class Ship and a class Cabin.

Both of these classes support a common interface, say Query and Cabin is
part of Ship. Therefore,

class Ship implements Query
{
String name;
Cabin cabin;

public String getQuery()
{
}
}


class Cabin implements Query
{

public String getQuery()
{
}
}

Now, inside cabin.getQuery() I need to know the ship.name value.
What's the best approach to achieve this? Should I pass a reference of
Ship in Cabin once a cabin object is created? Any other possible way?

Thanks in advance,
Markos Charatzas

Considering it doesn't make any sense for a Cabin to exist without a
Ship, I'd pass the Ship to the constructor of Cabin, thus:

class Cabin implements Query {
private Ship myShip;

public Cabin(Ship ship) {
myShip = ship;
}

public String getQuery() {
return myShip.getQuery();
}
}
 
A

Adam

Considering it doesn't make any sense for a Cabin to exist without a
Ship, I'd pass the Ship to the constructor of Cabin, thus:

class Cabin implements Query {
private Ship myShip;

public Cabin(Ship ship) {
myShip = ship;
}

public String getQuery() {
return myShip.getQuery();
}
}

Another possibility is to make Cabin a public nested
(inner) class of ship. Then it automaticaly has a
reference to its owning ship. Even creating
cabins is safer then - you have to have a ship
to create a cabin:
Ship ship = new Ship();
Ship.Cabin cabin = ship.new Cabin();
There is no way you can create a cabin not
belonging to any ship.
As for Barry's suggestion (above), it still would be
possible to do new Cabin(null). Even
if a NullPointerException was thrown from the Cabin's ctor
you would not know it until runtime.
With nested class it is the compiler's (not programmer's) responsibility
to assure that each cabin has an owning ship.

Disadvantage of this approach is having one big source file
for two classes. That's why probably many programmers
avoid this way of implementing aggregation (yes, me too)

Adam
 
M

Markos Charatzas

Thanx a lot for ur fast responses.

Another thing to consider is that these classes are generated from an
XML file using digester, which makes things a bit more complicated :(

I really dont like the idea of making it an inner class, though its a
way of doing it.... :(

Markos
 
R

Red Orchid

Adam said:
Disadvantage of this approach is having one big source file
for two classes. That's why probably many programmers
avoid this way of implementing aggregation (yes, me too)


another disadvantage may be as follow:

for implementing composite/aggregation,
i think that the nested-class way is *hard-coding* one.
that is,
it may cause hardness of source's re-use/maintenance.


for example,
---------------------------------------------
public class Ship {
...
class Cabin {
...
}
...
}
---------------------------------------------

'Ship' must have the *only one* kind of 'Cabin'. but,
in this source's maintenance time,
it may be requested that 'Ship' must have more than one
kinds of 'Cabin'. in this case,
'Ship' can not be re-used without change of the source.

moreover, (as i know as)
java must have the *only one* 'public' class in one file.
that is, 'Cabin' can not be re-used in other kinds of
ship class.
 
A

Adam

'Ship' must have the *only one* kind of 'Cabin'. but,
in this source's maintenance time,
it may be requested that 'Ship' must have more than one
kinds of 'Cabin'. in this case,
'Ship' can not be re-used without change of the source.
I don't really get that.
How about an example?
I think there's nothing what may
prevent you from having multiple
kinds of Cabin (i guess you mean subclasses of Cabin)
without touching the code of Ship.
moreover, (as i know as)
java must have the *only one* 'public' class in one file.
that is, 'Cabin' can not be re-used in other kinds of
ship class.

That is not true. Only one public most outer class - yes.
But public outer class and public inner class are OK.

As an example for my point of view - check this out:
THREE FILES.
FILE 1: Ship.java
public class Ship
{
public Ship(){ System.out.println(getClass().getName() + "
constructed."); }
public Cabin createCabin() { return new Cabin(); }
public class Cabin
{
protected Cabin(){ System.out.println(getClass().getName() + "
constructed."); }
}
}

FILE 2: AdvShip.java
public class AdvShip extends Ship
{
public AdvShip(){ System.out.println(getClass().getName() + "
constructed."); }
public Cabin createCabin() { return new AdvCabin(); }
public class AdvCabin extends Cabin
{
protected AdvCabin(){ System.out.println(getClass().getName() + "
constructed."); }
}
}

FILE 3: ShipTest.java
public class ShipTest
{
public static void main(String[] args)
{
System.out.println("Playing with ship...");
Ship ship = new Ship();
ship.createCabin();

System.out.println("Playing with advanced ship...");
ship = new AdvShip();
ship.createCabin();
}
}

Compile and run java ShipTest

Adam
 
R

Red Orchid

I don't really get that.
How about an example?
I think there's nothing what may
prevent you from having multiple
kinds of Cabin (i guess you mean subclasses of Cabin)
without touching the code of Ship.


---------------------- snip -------------------


That is not true. Only one public most outer class - yes.
But public outer class and public inner class are OK.

As an example for my point of view - check this out:
THREE FILES.
FILE 1: Ship.java
public class Ship
{

---------------------- snip -------------------

Compile and run java ShipTest


i have the following conceptions in my experience.

=======================================================
<< composite/aggregation relation >>

#1)
o_1 exist independently and have meanings independently.
o_2 has o_1.
for example, maybe...
o_1 is an apple and o_2 a gift.

#2)
o_1 exist independently but do not have meanings independently.
o_2 has o_1.
for example, maybe...
o_1 is an cpu and o_3 a computer.

#3)
both #1 and #2 have the phrase _'exist independently'_.


<< re-use conception of object-orient model >>

#4)
the conception has the purpose of decreasing efforts
of project's development/maintenance. the purpose is
achieved by the design of _'exist independently'_.
=======================================================

'inner' structure (class) _can not exist independently_.
in java,
the only one public/non-innner class of one file can exist
_independently_ in relation to other files.


i think that the relation of 'Ship' and 'Cabin' is
composite/aggregation relation.

so,
if a programmer designs 'Cabin' as inner class of 'Ship',
he harms 'independence' of composite/aggregation relation.
it inceases the efforts of maintenance/re-use.

as extremly example, there is a ship that do not have a cabin.
in this case,
a programmer need not maintain of the source of the cabin.


Now,
let consider about re-using 'Cabin'

your example uses inheritance.
when i read your article, i smiled on your example
because i thought the following code of yours is good.
 
B

BarryNL

Red said:
[email protected]:





i have the following conceptions in my experience.

=======================================================
<< composite/aggregation relation >>

#1)
o_1 exist independently and have meanings independently.
o_2 has o_1.
for example, maybe...
o_1 is an apple and o_2 a gift.

#2)
o_1 exist independently but do not have meanings independently.
o_2 has o_1.
for example, maybe...
o_1 is an cpu and o_3 a computer.

#3)
both #1 and #2 have the phrase _'exist independently'_.


<< re-use conception of object-orient model >>

#4)
the conception has the purpose of decreasing efforts
of project's development/maintenance. the purpose is
achieved by the design of _'exist independently'_.
=======================================================

'inner' structure (class) _can not exist independently_.
in java,
the only one public/non-innner class of one file can exist
_independently_ in relation to other files.


i think that the relation of 'Ship' and 'Cabin' is
composite/aggregation relation.

so,
if a programmer designs 'Cabin' as inner class of 'Ship',
he harms 'independence' of composite/aggregation relation.
it inceases the efforts of maintenance/re-use.

as extremly example, there is a ship that do not have a cabin.
in this case,
a programmer need not maintain of the source of the cabin.


Now,
let consider about re-using 'Cabin'

your example uses inheritance.
when i read your article, i smiled on your example
because i thought the following code of yours is good.

Of course, in this example, you'd probably want to use a Builder
instead, eg:

ShipBuilder builder = new ShipBuilder();
builder.createShip("QE2", ShipBuilder.CRUISE_LINER);
builder.addCabin("E1", ShipBuilder.LUXURY_CABIN);
builder.addCabin("D2", ShipBuilder.STANDARD_CABIN);
.... etc.
Ship myShip = builder.getShip();

Which would mean the client never needs to care or know about the actual
classes used to build the Ship because this is encapsulated in the
ShipBuilder class.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top