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 / September 2007

Tip: Looking for answers? Try searching our database.

Using an enum in a constructor

Thread view: 
Wojtek - 20 Sep 2007 21:33 GMT
Given the following:
---------------------------------
public class Foo
{
 private static final int DEFAULT_LENGTH = 30;
 private Type ivType;
 private int  ivLength;

 public enum Type
 {
   OTHER,
   FIXED,
   VARIABLE;
 }

 public Foo(Type type)
 {
   this(type,DEFAULT_LENGTH);
 }

 public Foo(Type.VARIABLE varType, int length)
 {
   this(varType,length);
 }

 private Foo(Type type, int length)
 {
   super();
   ivType = type;
   ivLength = length;
 }
}
---------------------------------

The compiler complains that Type.VARIABLE cannot be used. Obviously
what I want is that if the Type is VARIABLE, then I want the length in
the constructor, otherwise I will use the default length.

And yes I know I can have a constructor that only takes (int length)
and then assume that the Type is VARIABLE. That is not the point here.

Signature

Wojtek :-)

Gary Coulbourne - 20 Sep 2007 22:13 GMT
> The compiler complains that Type.VARIABLE cannot be used. Obviously what
> I want is that if the Type is VARIABLE, then I want the length in the
> constructor, otherwise I will use the default length.

I don't believe you can do what you're asking in Java as it stands.  All
of the elements of your enum are of type Type.  So Type VARIABLE isn't
special in any way that would allow the constructor to differentiate.
You could, perhaps, make a function that took variable arguments, and if
the first argument was of type VARIABLE, only then look to the second
argument.  But, then you'd lose compile-time type safety.

Peace,
Gary

Signature

--------------------------------------------------------------------
   Gary Coulbourne                        Software Developer
                                          C/C++, Java, Perl, Python

Wojtek - 20 Sep 2007 22:40 GMT
Gary Coulbourne wrote :

>> The compiler complains that Type.VARIABLE cannot be used. Obviously what
>> I want is that if the Type is VARIABLE, then I want the length in the
>> constructor, otherwise I will use the default length.
>
> I don't believe you can do what you're asking in Java as it stands.

That is what I thought. It would be nice to be able to enforce this
through type safety though.

> All
> of the elements of your enum are of type Type.  So Type VARIABLE isn't
> special in any way that would allow the constructor to differentiate.

Well yes, except that all the enum elements are there. The way I see
it, the enum is the type, but the enum elements are a enum "sub-type",
statically created the first time the class is used. The run-time
should be able to differentiate between them.

Signature

Wojtek :-)

Lasse Reichstein Nielsen - 21 Sep 2007 00:20 GMT
> Well yes, except that all the enum elements are there. The way I see
> it, the enum is the type, but the enum elements are a enum "sub-type",

No, they are values, not types (even though there might be a separate
anonymous class hidden in the implementation).
An enumerated type has a fixed number of values.

What you might want is a constructor:

 public Foo(int length) {
   this(Type.VARIABLE, length);
 }

or if you that's too obscure (it probably is), use a factory method
with a telling name:

 public static Foo createVariabelFoo(int length) {
   return new Foo(Type.VARIABLE, length);
 }

/L
Signature

Lasse Reichstein Nielsen  -  lrn@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
 'Faith without judgement merely degrades the spirit divine.'

Daniel Pitts - 20 Sep 2007 22:16 GMT
> Given the following:
> ---------------------------------
[quoted text clipped - 39 lines]
> --
> Wojtek :-)

Try using the Static Factory approach instead

public class Foo {
 enum Type {
   a, b, c
 }

 private Foo(Type type, int length) {
     // ...
 }

 public static Foo createVariable(int length) {
      return new Foo(Type.a, length);
 }

 public static Foo createSomething(Type type) {
      return new Foo(type, DEFAULT_LENGTH;
 }
 public sattic Foo createSomething(Type type, int length) {
      return new Foo(type, length);
 }
}
Wojtek - 20 Sep 2007 22:34 GMT
Daniel Pitts wrote :
>> Given the following:
>> ---------------------------------
[quoted text clipped - 62 lines]
>   }
> }

This is the same as having a constructor which takes just (int length).
I still need to make an assumption that type is VARIABLE.

Signature

Wojtek :-)

Daniel Pitts - 20 Sep 2007 22:59 GMT
> Daniel Pitts wrote :
>
[quoted text clipped - 70 lines]
> --
> Wojtek :-)

Its not an assumption, its explicit by the name of the method
"createVariable"!

In general though, if you have a "Type" token, you might be going
about your solution the wrong way.  Have you considered using a more
polymorphic approach?

abstract class Foo {
}

class VariableFoo extends Foo {
}

class OtherFoo extends Foo {
}

etc...

That way, the "Type" of foo, is actually the *type* of foo! (Go
figure).

Or, if the Type can change over time, use the State pattern (same
idea, just wrapper)

class Foo {
  FooType type;

  public Foo(FooType type) {}
}

abstract class FooType {
}

class FooVariable extends FooType {
  FooVariable(int length) {}
}

class FooOther extends FooType {
}
Wojtek - 20 Sep 2007 23:29 GMT
Daniel Pitts wrote :
>> This is the same as having a constructor which takes just (int length).
>> I still need to make an assumption that type is VARIABLE.
>>
> Its not an assumption, its explicit by the name of the method
> "createVariable"!

Sorry, did not read it through :-(

> In general though, if you have a "Type" token, you might be going
> about your solution the wrong way.  Have you considered using a more
[quoted text clipped - 10 lines]
>
> etc...

Yes, it could be done that way. I am refactoring the class and its use
anyways, so 6 == dozen/2, though your six has benefits.

I am converting:

public static final int VARIABLE = 0x01;
public static final int OTHER    = 0x02;

etc, and converting to an enum seemed a natural approach

I only have 800+ places to refactor...

Signature

Wojtek :-)

Daniel Pitts - 21 Sep 2007 00:09 GMT
> Daniel Pitts wrote :
>
[quoted text clipped - 35 lines]
> --
> Wojtek :-)

:-)

Moving from "int" style type-codes to "enum" style is a step in the
right direction.  Replacing types-codes/switches with polymorphism is
the real goal of an OO designer.

I suggest reading a good refactoring book. I've read both
"Refactoring" by Martin Fowler, and "Refactoring to Patterns" by
Joshua Kerievsky.  I would recommend either one (Kerievsky frequently
references Fowler).
Roedy Green - 21 Sep 2007 00:28 GMT
>public class Foo
>{
[quoted text clipped - 8 lines]
>    VARIABLE;
>  }

You have this as a nested inner instance class. I have always made my
enums separate top level classes.  Perhaps you are allowed to define
them as static inner classes.  Perhaps there are magic exceptions made
for enums to the usual nesting rules.  Is there a language lawyer
about?
Signature

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

Joshua Cranmer - 21 Sep 2007 00:38 GMT
>> public class Foo
>> {
[quoted text clipped - 14 lines]
> for enums to the usual nesting rules.  Is there a language lawyer
> about?

JLS §8.9 (I think; I haven't checked since Wednesday) says that all
enums are implicitly static classes and not inner instance classes.
Therefore:

public class Foo
{
  public enum Type { }
}

and

public class Foo
{
  public static enum Type { }
}

are equivalent.

Signature

Beware of bugs in the above code; I have only proved it correct, not
tried it. -- Donald E. Knuth

Wojtek - 21 Sep 2007 00:38 GMT
Roedy Green wrote :

>> public class Foo
>> {
[quoted text clipped - 14 lines]
> for enums to the usual nesting rules.  Is there a language lawyer
> about?

We have had this discussion before, but I do not remember seeing your
example.

If I use the above, then I reference it with Foo.Type.FIXED.

What does your separate top level enum class look like, and how do you
reference it?

Signature

Wojtek :-)

Daniel Pitts - 21 Sep 2007 16:20 GMT
> Roedy Green wrote :
>
[quoted text clipped - 27 lines]
> --
> Wojtek :-)

/* MySeperateEnum.java */
public enum MySeperateEnum {
  A,B,C;
}

/*SomeOtherClass.java*/
public class SomeOtherClass {
  MySeperateEnum value = MySeperateEnum.A;

}
Wojtek - 23 Sep 2007 19:21 GMT
Daniel Pitts wrote :
>> Roedy Green wrote :
>>
[quoted text clipped - 38 lines]
>
> }

Ah, ok, I see now. This enum beast is kind of a funny sort of class....

So I can create a separate class for the enum (as per your example), or
nest it in the class where it is used (as per my example).

So if it is being used elsewhere in the system I need two import
statements vs one.

I kind of prefer the nesting approach, as the location (and reference)
indicates the enums logical ownership.

Signature

Wojtek :-)

Daniel Pitts - 23 Sep 2007 20:00 GMT
Sorry if this gets double posted.  GG is on the fritz again!
> Daniel Pitts wrote :
>
[quoted text clipped - 42 lines]
>
> Ah, ok, I see now. This enum beast is kind of a funny sort of class....
Actually, it is in more ways than you might suspect.

enum MyEnum {
   A {
       public void doSomething() {
         System.out.println("Something on A");
       }
   },
   B{
       public void doSomething() {
         System.out.println("B does something");
       }
   },
   C{
       public void doSomething() {
         System.out.println("C you later!");
      }
   };

   public abstract void doSomething();
}

MyEnum is an abstract base class of MyEnum.A (and .B, etc..).  You can
add methods, fields (good practice to make those final), and even
constructors to the enum and members.  You can even add members to the
specifics (MyEnum.A) that aren't in the parent (MyEnum).

I've used this idiom to implement the flyweight pattern in conjunction
with the strategy/state pattern.  Although, I usually find that
eventually I need even more flexibility (better polymorphic
structure), and end up refactoring away from the enum approach.   Not
to say enums aren't a good interim step, or prototype step before that
approach.

> So I can create a separate class for the enum (as per your example), or
> nest it in the class where it is used (as per my example).
>
> So if it is being used elsewhere in the system I need two import
> statements vs one.
I don't count imports as statements personally. I think of them more
as directives. You can always give the fully qualified class name in
place of using the imports.

> I kind of prefer the nesting approach, as the location (and reference)
> indicates the enums logical ownership.
Indeed. If the enum has a logical owner, then it makes much sense to
have that owner, ahem, own it!

On the other hand, if it doesn't have a *single* logical owner (which
does happen on occasion), it should probably be its own separate
entity.

Good luck,
Daniel.
Roedy Green - 23 Sep 2007 23:09 GMT
>Ah, ok, I see now. This enum beast is kind of a funny sort of class....

Enums made no sense until I started decompiling code and seeing how
they work under the hood.  I have posted the results of my experiments
at http://mindprod.com/jgloss/enum.html
Signature

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

Lew - 23 Sep 2007 23:27 GMT
>> Ah, ok, I see now. This enum beast is kind of a funny sort of class....
>
> Enums made no sense until I started decompiling code and seeing how
> they work under the hood.  I have posted the results of my experiments
> at http://mindprod.com/jgloss/enum.html

I love that article.  It clarifies enum semantics for me.

I do have one small nit over it, with respect to specifics of nested class
terminology:
> I have managed to get nested static inner enums and nested instance inner enums to work as well,

There isn't actually a difference for enums:
> Nested enum types are implicitly static.
> It is permissable to explicitly declare a nested enum type to be static.
<http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.9>

Also, an "inner class" according to the JLS is the opposite of static nested,
which both are subcategories of nested classes:
> An /inner class/ is a nested class that is not explicitly or implicitly declared static.
(emphasis original)
<http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.1.3>

The terms as defined by the JLS are much more specific than they are in
general usage.

Signature

Lew

Roedy Green - 24 Sep 2007 00:03 GMT
>The terms as defined by the JLS are much more specific than they are in
>general usage.

I got in the habit of calling them "inner classes" and "static inner
classes" before someone explained the proper terminology.  I went over
the http://mindprod.com/jgloss/enum.html entry tightening the wording.
Signature

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

Joshua Cranmer - 23 Sep 2007 23:45 GMT
>> Ah, ok, I see now. This enum beast is kind of a funny sort of class....
>
> Enums made no sense until I started decompiling code and seeing how
> they work under the hood.  I have posted the results of my experiments
> at http://mindprod.com/jgloss/enum.html

In answer to your question:
   I wondered wonder why Sun didn't just use the enum ordinals directly
as case numbers.

My current understanding is that it is to promote binary compatibility:
changing the order of the enum constants wouldn't break the switch
statement under this scheme. Sun really does go far to try and keep code
binary-compatible. (I believe Andrew Thompson was the one who pointed
this out sometime over the summer)

Signature

Beware of bugs in the above code; I have only proved it correct, not
tried it. -- Donald E. Knuth

Roedy Green - 24 Sep 2007 00:53 GMT
On Sun, 23 Sep 2007 22:45:31 GMT, Joshua Cranmer
<Pidgeot18@verizon.net> wrote, quoted or indirectly quoted someone who
said :

>My current understanding is that it is to promote binary compatibility:
>changing the order of the enum constants wouldn't break the switch
>statement under this scheme. Sun really does go far to try and keep code
>binary-compatible.

Thanks. I have updated the entry http://mindprod.com/jgloss/enum.html
Signature

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

smcardle@smcardle.com - 21 Sep 2007 13:09 GMT
> Given the following:
> ---------------------------------
[quoted text clipped - 39 lines]
> --
> Wojtek :-)

So what about this then

public class Foo
{
 private static final int DEFAULT_LENGTH = 30;
 private Type ivType;
 private int  ivLength;

 public enum Type
 {
   OTHER,
   FIXED,
   VARIABLE;
 }

 public Foo(Type type)
 {
   this(type,DEFAULT_LENGTH);
 }

 public Foo(Type type, int length)
 {
     ivType = type;
     switch(type) {
     case VARIABLE:
         ivLength = DEFAULT_LENGTH;
         break;
     default:
         ivLength = length;

     }
 }
}

Steve
Lew - 21 Sep 2007 13:38 GMT
>      switch(type) {
>      case VARIABLE:
[quoted text clipped - 4 lines]
>
>      }

Nine times out of ten, a switch() like this is a red flag that polymorphism
should be used instead.

Signature

Lew



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



©2009 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.