Solved

Java custom types and subsets of types

Posted on 2014-07-22
5
171 Views
Last Modified: 2014-07-23
I have a bunch of unit types:
package units;

public enum Units {
  FAHRENHEIT,
  CELSIUS,
  KELVIN,
  FEET,
  INCHES,
  MILES,
  METERS;
}

Open in new window

and unit categories:
public enum TemperatureUnits = { FAHRENHEIT, CELSIUS, KELVIN }

Open in new window

public enum LengthUnits = {  FEET, INCHES, MILES, METERS }

Open in new window

Problem is as you can see all of my values are defined twice, and I'm sure that's going to lead to endless confusion.

I've also considered using a hierarchy of classes:

Units

    TemperatureUnits extends Units
    LengthUnits extends Units

        Fahrenheit extends TemperatureUnits
        Celsius extends TemperatureUnits
        Kelvin extends TemperatureUnits

        Inches extends LengthUnits
        Feet extends LengthUnits
        Miles extends LengthUnits
        Meters extends LengthUnits

Then I can do:
double value = myMeasurement.getValueAs(new Meters());

Open in new window

but it seems silly to create a class instance new Meters() when all I really need is the class type.

I'd like to be able to specify what range of units a method can accept:
    public double getValueAs(LengthUnits u) {
...
    public double getValueAs(TemperatureUnits u) {
....
    public double manipulate(Units u) {
....

Open in new window

Any suggestions?
0
Comment
Question by:deleyd
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
5 Comments
 
LVL 27

Assisted Solution

by:dpearson
dpearson earned 500 total points
ID: 40212196
Although you can't extend an enum to create a hierarchy you can implement an interface.

So how about this structure:

public interface Units {
}

public enum LengthUnits implements Units {
	FEET, INCHES, MILES ;

	public double convertToMeters(double value) {
                // Yes this math is a bit off...
		switch (this) {
			case FEET: return value / 3.0 ;
			case INCHES: return value / 36.0 ;
			case MILES: return value * 8000.0 / 5.0 ;
			default: throw new IllegalStateException("Unknown value in enum") ;
		}
	}
}

public enum TemperatureUnits implements Units {
	CELSIUS, FAHRENHEIT, KELVIN ;
}

Open in new window


Then you can write code like this:

            Units example = LengthUnits.FEET ;
            LengthUnits other = LengthUnits.INCHES ;

                // Convert 100 inches to meters
                double meters = LengthUnits.INCHES.convertToMeters(100)  ;

together with your methods taking Units or LengthUnits etc.

You can also define methods in the Units interface, which would need to be implemented by the enums - just like for a class - if you'd like to be able to call a method on a Units object.

Any good?

Doug
0
 

Author Comment

by:deleyd
ID: 40212261
Hmm, interesting.

How could I use this to pass a parameter to a method specifying what unit type I would like the return value to be in? The method would be in a different class.

Some methods can accept any unit, while other methods want a specific subtype of unit (as in Length, Temperature,...)
0
 
LVL 27

Assisted Solution

by:dpearson
dpearson earned 500 total points
ID: 40212281
The examples you posted earlier could all be written now.
If they're in different classes it would look like this:

public class A { public double getValueAs(LengthUnits u) ; }
public class B { public double getValueAs(TemperatureUnits u) ; }
public class C { public double manipulate(Units u) ; }

Here are some example calls:

A a = new A() :
a.getValueAs(LengthUnits.INCHES) ;

// Or we can use a variable if we prefer:
LengthUnits unitsForThisCalc = LengthUnits.MILES ;
a.getValueAs(unitsForThisCalc) ;

// This won't compile - it only takes LengthUnits
a.getValuesAs(TemperatureUnits.CELSIUS) ;

// But these are all fine, since they accept any Units
C c = new C() ;
c.manipulate(TempatureUnits.CELSIUS) ;
c.manipulate(LengthUnits.FEET) ;

Doug
0
 

Author Comment

by:deleyd
ID: 40212687
Thank you I think I see it now, I'll give it a try.

Somewhat related, is it true with Generics there's no way to create a Generic type T and pass parameters to the constructor? As in:
class MyClass<T>

public T myMethod() {
    int p1 = 5;
    String p2 = "Hello";

    T t = new T(p1,p2);  //not possible...
    return (t);
}

Open in new window

I've seen ways of creating type T passing no parameters to the constructor, but I don't think it's possible to create type T with parameters. Is that correct that it can't be done?
0
 
LVL 27

Accepted Solution

by:
dpearson earned 500 total points
ID: 40212836
Yeah I don't think that's possible.
I'd be surprised if you can even call the default constructor (the one with no parameters).

I think the root issue is that in Java, the generic information is all discarded at runtime.
So there's no "T" left to instantiate at runtime (it's only available at compile time - but clearly the runtime would need it as well to call a constructor on the right class).


You should however be able to get the desired behavior through reflection.  You'd need to pass in both "T" and the class of T as a String.  Then you can call the constructor for that class, passing parameters etc.  The code's a bit ugly and verbose but should work fine.  Here's a sample tutorial on how to do this:
http://tutorials.jenkov.com/java-reflection/constructors.html

You'd end up instantiating the class with something like

MyClass<Integer, Integer.class.toString()) <-- second parameter passes in the name of the class so you can instantiate it at runtime.  The first parameter you'd use for type checking like normal.

Doug
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
runtime exception 2 66
ejb message driven bean mdb creation steps 2 54
American Express @Work site and Java 4 93
Java array 21 149
For beginner Java programmers or at least those new to the Eclipse IDE, the following tutorial will show some (four) ways in which you can import your Java projects to your Eclipse workbench. Introduction While learning Java can be done with…
Java Flight Recorder and Java Mission Control together create a complete tool chain to continuously collect low level and detailed runtime information enabling after-the-fact incident analysis. Java Flight Recorder is a profiling and event collectio…
Viewers learn about the third conditional statement “else if” and use it in an example program. Then additional information about conditional statements is provided, covering the topic thoroughly. Viewers learn about the third conditional statement …
Viewers will learn about the regular for loop in Java and how to use it. Definition: Break the for loop down into 3 parts: Syntax when using for loops: Example using a for loop:
Suggested Courses

734 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question