Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / March 2008

Tip: Looking for answers? Try searching our database.

How to specify a parameter

Thread view: 
Luca D. - 15 Mar 2008 19:18 GMT
Hello!
When I create an instance of a class, I have to specify a direction,
which can be "Left" or "Right".
I thought about:

public class Object {
   private String direction;

   public Object(String direction) {
       this.direction = direction;
   }
}

Object o = new Object("Left"/"Right");

Otherwise:

public class Object {
   private final int left = 0;
   private final int right = 1;
   private int direction;

   public Object(int direction) {
       this.direction = direction;
   }
}

Object o = new Object(0/1);

In this case everyone must know that left = 0 and right = 1.
Is there a common way/design pattern to solve this kind of problem?
Thank you.
grasp06110 - 15 Mar 2008 19:38 GMT
> Hello!
> When I create an instance of a class, I have to specify a direction,
[quoted text clipped - 30 lines]
> Is there a common way/design pattern to solve this kind of problem?
> Thank you.

Hi,

Good question (shows lots of thought towards design that will save you
a heart ache in the long run if you continue to think of these things
up front rather than wait for a project to get large enough and
complex enough for these things to become significant).

If you are using a more recent version of Java (1.5 or higher) you can
use an enumeration (google java enumeration should give you everything
you need). 1.4 or earlier it was common to do something like declare a
public static final variables, something like:

public class Thingy {

 public static final int LEFT = 0;

 public static final int RIGHT = 1;

 private int direction;

 public Thingy(int initDirection) {
   this.direction = initDirection;
 }

}

Thingy thing = new Thingy(Thingy.LEFT);

Also, Josh Bloch had a very good book of idioms called Effective Java
that had an excellent section that described how to roll your own
enumerations in Java pre 1.5.

Have Fun,
John
Eric Sosman - 15 Mar 2008 19:40 GMT
> Hello!
> When I create an instance of a class, I have to specify a direction,
> which can be "Left" or "Right".
> I thought about:
>
> public class Object {

    Perhaps you should name your class "String" or "System"
to avoid confusion.  ;-)

>     private String direction;
>
[quoted text clipped - 21 lines]
> In this case everyone must know that left = 0 and right = 1.
> Is there a common way/design pattern to solve this kind of problem?

    Several, with various advantages and disadvantages.

    public class Obtuse {
       public static final int LEFT = 0;
       public static final int RIGHT = 1;

       private int direction;

       public Obtuse(int direction) {
           this.direction = direction;
       }
    }
    ...
    Obtuse o = new Obtuse(Obtuse.LEFT);

Advantage: Simplicity.  Disadvantage: Allows `new Obtuse(-42)'.

    public class Obnoxious {
       private static class Direction {
           private Direction() { }
       }
       public static final Direction LEFT = new Direction();
       public static final Direction RIGHT = new Direction();

       private Direction direction;

       public Obnoxious(Direction direction) {
           this.direction = direction;
       }
    }
    ...
    Obnoxious o = new Obnoxious(Obnoxious.LEFT);

Advantage: Built-in type safety.  Disadvantage: Clutter.

    public class Obese {
       public enum Direction { LEFT, RIGHT }

       private Direction direction;

       public Obese(Direction direction) {
           this.direction = direction;
       }
    }
    ...
    Obese o = new Obese(Obese.LEFT);

Advantage: It's all the rage.  Disadvantage: More clutter.

Signature

Eric Sosman
esosman@ieee-dot-org.invalid

Roedy Green - 15 Mar 2008 22:56 GMT
On Sat, 15 Mar 2008 11:18:06 -0700 (PDT), "Luca D."
<ldantona@gmail.com> wrote, quoted or indirectly quoted someone who
said :

>In this case everyone must know that left = 0 and right = 1.
>Is there a common way/design pattern to solve this kind of problem?

1. boolean

2. named boolean e.g.  final static boolean LEFT = false;

3. named int constant e.g. final static int LEFT = 0;

4. enum {lEFT,RIGHT;}
Signature


Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Mark Space - 15 Mar 2008 23:28 GMT
> 4. enum {lEFT,RIGHT;}

This is the best idea.  enum {LEFT, RIGHT} is type safe and much better
than ints or strings.

(Also, do NOT use a class named Object.  Hello?)

If for some reason you are using an older compiler that doesn't have
enums, take grasp's advice and get Effective Java.  The pattern uses
classes instead of ints.  This makes the constants you expose much more
type safe.  From memory, it goes something like this.

final public class Direction {

   public final static Direction LEFT = new Direction();
   public final static Direction RIGHT = new Direction();

   private Direction() {
   }
}

This can get fancier (you should probably override the toString()
method), but that's the gist. Now you have Direction.LEFT and
Direction.RIGHT, and no one can ever change that, or substitute a
different type or value.  The type is Direction, as in

public void someMethod ( Direction dir ) { ... }.
Luca D. - 16 Mar 2008 17:59 GMT
Thanks everyone, I think Enums are the best solution in my case.

> (Also, do NOT use a class named Object.  Hello?)

Of course that was just a (bad) example.. Hello? World :)
Mark Space - 16 Mar 2008 18:40 GMT
> Thanks everyone, I think Enums are the best solution in my case.
>
>> (Also, do NOT use a class named Object.  Hello?)
>
> Of course that was just a (bad) example.. Hello? World :)

Yes it was.  I think we all knew that, but we also get folks who have
named their own class Vector, or String, or Integer, and a big mess
usually ensues.  I'll admit it was the first time I'd seen anyone use
Object though.

This group prefers precision, just because people do make those kinds of
mistakes.  It's best post real code, and compilable code too, not just
snippets.  Silly examples will get you flak from folks who assume that
what you posted is in fact what your code is.

Check out the SSCCE and try to do that.  It'll also help you get answers
quicker:

<http://homepage1.nifty.com/algafield/sscce.html>
Luca D. - 19 Mar 2008 11:11 GMT
Let's see another example about the same topic.

public abstract class AbstractVehicle {
   public String GetType();
}

public abstract class ConcreteVehicle1 extends AbstractVehicle {
   public String GetType() {
       return "Vehicle1";
   }
}

public abstract class ConcreteVehicle1 extends AbstractVehicle {
   public String GetType() {
       return "Vehicle2";
   }
}

public class VehicleManager {
   public void DoSomething(AbstractVehicle vehicle) {
       if(vehicle.GetType.equals("Vehicle1"))
           ...
       else if(vehicle.GetType.equals("Vehicle2"))
           ...
       ...
   }
}

Which is the best way to plan this situation with polymorphism?
Thanks to what you taught me, I'd use an enum:

public enum VehicleType {
   VEHICLE1,
   VEHICLE2
}

And the rest of the code would be:

public abstract class AbstractVehicle {
   public VehicleType GetType();
}

public abstract class ConcreteVehicle1 extends AbstractVehicle {
   public VehicleType GetType() {
       return VehicleType.VEHICLE1;
   }
}

public abstract class ConcreteVehicle2 extends AbstractVehicle {
   public VehicleType GetType() {
       return VehicleType.VEHICLE2;
   }
}

public class VehicleManager {
   public DoSomething(AbstractVehicle vehicle) {
       if(vehicle.GetType() == VehicleType.VEHICLE1)
           ...
       else if(vehicle.GetType() == VehicleType.VEHICLE2)
           ...
       ...
   }
}

Is it good to use an enumerator which contains the type/name of every
subclass?
Hoping this time the names for classes I used are better, thanks in
advance! :)
Roedy Green - 19 Mar 2008 11:18 GMT
On Wed, 19 Mar 2008 03:11:33 -0700 (PDT), "Luca D."
<ldantona@gmail.com> wrote, quoted or indirectly quoted someone who
said :

>public abstract class ConcreteVehicle1 extends AbstractVehicle {
>    public VehicleType GetType() {
>        return VehicleType.VEHICLE1;
>    }
>}

why not just append your ConcreteVehicle1 methods to the VEHICLE1
enum?  Then you don't even need a getType method.
Signature


Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Luca D. - 19 Mar 2008 11:55 GMT
On 19 Mar, 11:18, Roedy Green <see_webs...@mindprod.com.invalid>
wrote:
> why not just append your ConcreteVehicle1 methods to the VEHICLE1
> enum?  Then you don't even need a getType method.

Do you mean to remove the subclasses and work directly with the enum?
I think I can't do that because ConcreteVehicles are Thread.
RedGrittyBrick - 19 Mar 2008 11:41 GMT
> Let's see another example about the same topic.
>
[quoted text clipped - 59 lines]
>     }
> }

The above is riddled with bugs.

> Is it good to use an enumerator which contains the type/name of every
> subclass?

1) Maybe you could use vehicle.getClass().getName() instead?

2) The need to do so suggests the design is poor. Whatever is happening
in the 'if' statements, should perhaps be replaced by an instance method
of AbstractVehicle that the subtypes implement (or override) differently.

Instead of
       if(vehicle.GetType() == VehicleType.VEHICLE1)
           ...
       else if(vehicle.GetType() == VehicleType.VEHICLE2)
           ...
       ...
Maybe you can do
       vehicle.dotDotDot();

Here's a corrected SSCCE based on your buggy code above:
---------------------------------------8<---------------------------------
public class InheritTest1 {
    public static void main(String[] args) {
        InheritTest1 x = new InheritTest1();
        x.new VehicleManager().doSomething(x.new ConcreteVehicle1());
    }

    public enum VehicleType {
        VEHICLE1, VEHICLE2
    }

    public abstract class AbstractVehicle {
        public abstract VehicleType getType();
    }

    public class ConcreteVehicle1 extends AbstractVehicle {
        public VehicleType getType() {
            return VehicleType.VEHICLE1;
        }
    }

    public class ConcreteVehicle2 extends AbstractVehicle {
        public VehicleType getType() {
            return VehicleType.VEHICLE2;
        }
    }

    public class VehicleManager {
        public void doSomething(AbstractVehicle vehicle) {
            if (vehicle.getType() == VehicleType.VEHICLE1)
                System.out.println("Aha!");
            else if (vehicle.getType() == VehicleType.VEHICLE2)
                System.out.println("Oho!");
        }
    }

}
---------------------------------------8<---------------------------------
The main is a bit convoluted just so I can wrap everything into a single
class for ease of cut&paste&compile.

Here's another (better?) way to do achieve the same outcome:
---------------------------------------8<---------------------------------

public class InheritTest2 {
    public static void main(String[] args) {
        InheritTest2 x = new InheritTest2();
        x.new VehicleManager().doSomething(x.new ConcreteVehicle1());
    }

    public abstract class AbstractVehicle {
        public abstract void doSomething();
    }

    public class ConcreteVehicle1 extends AbstractVehicle {
        public void doSomething() {
            System.out.println("Aha!");
        }
    }

    public class ConcreteVehicle2 extends AbstractVehicle {
        public void doSomething() {
            System.out.println("Oho!");
        }
    }

    public class VehicleManager {
        public void doSomething(AbstractVehicle vehicle) {
            vehicle.doSomething();
        }
    }

}
---------------------------------------8<---------------------------------
Whether the above meets your needs is something I can't determine from
the example you posted. I think it illustrates a better way to think
about such problems but there will be some needs that can't be handled
this way.

> Hoping this time the names for classes I used are better,

Much better :-)

I'd have used Car and Truck instead of ConcreteVehicle1 and
ConcreteVehicle2 but maybe I have too much difficulty with abstract
expressions of concepts.

Signature

RGB

Luca D. - 19 Mar 2008 11:59 GMT
> Instead of
>         if(vehicle.GetType() == VehicleType.VEHICLE1)
[quoted text clipped - 4 lines]
> Maybe you can do
>         vehicle.dotDotDot();

I can't do that, the Manager can't delegate the vehicles in this way,
it must know the type of vehicle to do other things..
Maybe the best solution is x.getClass().getName() and then check the
String.
Thanks for all your answers!
Lew - 19 Mar 2008 13:40 GMT
>> Instead of
>>         if(vehicle.GetType() == VehicleType.VEHICLE1)
[quoted text clipped - 9 lines]
> Maybe the best solution is x.getClass().getName() and then check the
> String.

No, RedGrittyBrick's solution is the best.

Your statement "I can't do that" is actually mistaken.

Checking the type and branching is an antipattern for which polymorphism is
the solution.

If your [Mis]Manager class "must know the type of the vehicle", then you
aren't taking advantage of the object-oriented programming skill set.  You
have broken encapsulation.

The vehicle must be the only thing that knows how to fulfill its public
contract.  Whatever the Manager wants to do is better handled via a
polymorphic method call.

Signature

Lew

Mark Space - 19 Mar 2008 22:47 GMT
>> Instead of
>>         if(vehicle.GetType() == VehicleType.VEHICLE1)
[quoted text clipped - 10 lines]
> String.
> Thanks for all your answers!

I have to ditto what Lew and Red said.  I don't like the enums either,
anytime you need to do this it's basically broken.  It feels like you're
trying to implement one of those "roll your own RTTI" systems people
feel they need to use with C++.

I'm curious: what Manager you are using?  Did you get it as part of a
package or did your team write it themselves?


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.