Solved

Java custom types and subsets of types

Posted on 2014-07-22
5
158 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
  • 3
  • 2
5 Comments
 
LVL 26

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 26

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 26

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

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Introduction This article is the second of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers the basic installation and configuration of the test automation tools used by…
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 learn about the scanner class in this video and are introduced to receiving user input for their programs. Additionally, objects, conditional statements, and loops are used to help reinforce the concepts. Introduce Scanner class: Importing…

760 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

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now