Hi,
I am amazed at the following way transforming a Class into different
Class on the fly(Expert becomes Singer, Chef or Painter). Could you
throw in some comment for me? Is this called Strategy design pattern?
Now I do feel "has-a" is more powerful than "is-a".
Thank you very much.
<code>
interface Talent
{
void showTalent();
}
class Singing implements Talent
{
public void showTalent()
{
System.out.println("do-rei-mei");
}
}
class Painting implements Talent
{
public void showTalent()
{
System.out.println("yellow, blue, red");
}
}
class Cooking implements Talent
{
public void showTalent()
{
System.out.println("gong-bao chicken");
}
}
//Skills of Expert is undecided right now. His skills will be set on the
fly. I am truely amazed at how powerful this technique it is.
public class Expert {
private Talent myTalent = null; //undecided yet
public Expert(Talent t)
{
myTalent = t;
}
public void serve()
{
myTalent.showTalent();
}
public static void main(String[] args)
{
Expert anExpert = new Expert(new Singing()); //this expert is singer
anExpert.serve();
anExpert = new Expert(new Cooking()); //this expert is Chef
anExpert.serve();
anExpert = new Expert(new Painting()); //this expert is Painter
anExpert.serve();
}
}
</code>
Simon Brooke - 06 Oct 2006 15:18 GMT
> Hi,
>
> I am amazed at the following way transforming a Class into different
> Class on the fly(Expert becomes Singer, Chef or Painter).
No, it doesn't. Expert remains Expert. A Singer remains a Singer. The fact
that a singer is a kind of expert and inherits behaviour from expert is
just the core idea of object oriented programming. Yes, it's a powerful
abstraction...

Signature
simon@jasmine.org.uk (Simon Brooke) http://www.jasmine.org.uk/~simon/
Morning had broken. I found a rather battered tube of Araldite
resin in the bottom of the toolbag.
Patricia Shanahan - 06 Oct 2006 15:29 GMT
> Hi,
>
[quoted text clipped - 3 lines]
>
> Now I do feel "has-a" is more powerful than "is-a".
For something like skill, I would go a stage further, and use "has-some"
rather than "has-a". Many people have more than one skill. Supporting
one-to-many relationships is another advantage of composition over
inheritance.
Patricia
Shawn - 06 Oct 2006 16:27 GMT
Thank you for your comments. Now see something new I did in the Class
MyHouse. The chair is broken. To fix it, write a class implementing
Talent interface, plug it into Expert. Now the Expert with Talent of
RepairingFurniture (a carpenter actually) is in my house now.
Expert.server() will fix the broken chair.
<code>
interface Talent
{
void showTalent();
}
class Singing implements Talent
{
public void showTalent()
{
System.out.println("do-rei-mei");
}
}
class Painting implements Talent
{
public void showTalent()
{
System.out.println("yellow, blue, red");
}
}
class Cooking implements Talent
{
public void showTalent()
{
System.out.println("gong-bao chicken");
}
}
class Expert
{
private Talent myTalent = null;
public Expert(Talent t)
{
myTalent = t;
}
public void serve()
{
myTalent.showTalent();
}
public static void main(String[] args)
{
Expert anExpert = new Expert(new Singing()); //this expert is singer
anExpert.serve();
anExpert = new Expert(new Cooking()); //this expert is Chef
anExpert.serve();
anExpert = new Expert(new Painting()); //this expert is Painter
anExpert.serve();
}
}
public class MyHouse
{
private boolean chairBroken = true;
public boolean isChairBroken()
{
return this.chairBroken;
}
private class RepairingFurniture implements Talent
{
public void showTalent()
{
if (chairBroken == true)
{
chairBroken = false;
}
}
} //end of private class
public static void main(String[] args)
{
MyHouse myHouse = new MyHouse();
if (myHouse.isChairBroken())
{
System.out.println("The chair needs to be fixed");
}
else
{
System.out.println("The chair has been fixed");
}
Expert anExpert = new Expert(myHouse.new RepairingFurniture()); //an
Expert with talent of RepairingFurniture (a carpenter) is in my house now.
anExpert.serve(); //this expert will fix the chair for us!!!
if (myHouse.isChairBroken())
{
System.out.println("The chair needs to be fixed");
}
else
{
System.out.println("The chair has been fixed");
}
}
}
</code>
Thomas Weidenfeller - 06 Oct 2006 17:41 GMT
> Thank you for your comments. Now see something new I did in the Class
> MyHouse. The chair is broken. To fix it, write a class implementing
> Talent interface, plug it into Expert. Now the Expert with Talent of
> RepairingFurniture (a carpenter actually) is in my house now.
> Expert.server() will fix the broken chair.
Ok, so you like to play with object-oriented features. Then the
following two books might be of interest for you. However, before you go
out and buy them, check them out in a library. They are on professional
level and they are not available for pocket money:
Gamma; Helm; Johnson; Vlissides: Design Patterns: Elements of Reusable
Object-Oriented Software
Fowler: Analysis Patterns: Reusable Object Models
Oh, and one thing. In real world applications it is also a good idea to
know when to stop building abstractions and adding indirections and to
just write some straight-forward code to get things done. This is a
matter of experience.
In your example, separating Expert and Talent in a real world
application might be overengineering. If there are, for example, only
Experts who can have Talent (and not, let's say Dogs or Laymen), and if
there are only few Talents of interest, and if an Expert's role always
only requires to have one single Talent, then using
interface Expert { ... }
class Singer implements Expert { ... }
class Painter implements Expert { ... }
class Cook implements Expert { ... }
might also get the job done in a simple, maintainable, easy to
understand way. It is not as sophisticated and beautiful as modeling
Talent separately, but it might well do in practice.
/Thomas

Signature
The comp.lang.java.gui FAQ:
http://gd.tuwien.ac.at/faqs/faqs-hierarchy/comp/comp.lang.java.gui/
ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq
Lew - 07 Oct 2006 18:04 GMT
> public class Expert {
> private Talent myTalent = null; //undecided yet
The initialization to null is redundant. Instance variables are initialized
to "zero-like" values (null for references) by default.
Also, stating "undecided yet" in a comment is misleading since the constructor
sets the variable in this example, so no fully-constructed instance will ever
see that "yet" moment.
> public Expert(Talent t)
> {
> myTalent = t;
> }
In other words, all clients will see your Expert object only after it's fully
constructed, so the "yet" moment is practically non-existent.
BTW, you should probably forbid null for the constructor argument:
public Expert(Talent t)
{
if ( t == null )
{
throw new NullPointerException( "null talent" );
}
myTalent = t;
}
Otherwise serve() could throw that exception for you, but without useful
message verbiage. That would be an example of a bug from earlier (the
constructor) showing up later (the method call), a common programming problem
that confounds analysis and repair.
- Lew