Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can one create an abstract, immutable class?

Tags:

Here's the short version. First and foremost: I want my class to be immutable. I know that a class can't be both abstract and final. What I'm asking is: is there a way to only allow inner classes to extend and implement the outer, abstract class? This may not be the best method to achieve my immutable goals, so if somebody has a better design, I would love to hear it.

I am writing a class for vector operations -- as in physics and engineering, not the programming sense. (I'm also aware that JScience has a package for this kind of stuff. I want to write my own, and keep it simple.)

I like the pattern used in Java's geometry package, wherein, say, a Line2D can be created using one of two precision levels: float or double.

public abstract class Line2D {     public static class Float extends Line2D { /* Implementation */ }     public static class Double extends Line2D { /* Implementation */ } } 

This is a feature I would really like to incorporate and expand upon in my class, so I created the following:

public abstract class Vector2D {      public final static class Integer extends Vector2D {          // Component length projected along x/y axis, respectively         final private int i, j;          public Integer( int i, int j ) {             this.i = i;             this.j = j;         }          public Object doStuff() { /* vector operations */ }     }      public final static class Float extends Vector2D {         // Identical to Vector2D.Integer, except with floats     }      public final static class Double extends Vector2D { /* Same Idea */ }      // Outer class methods and whatnot } 

Obviously, Vector2D.Integer, Vector2D.Float, and Vector2D.Double are all final. Is there any way to make Vector2D final to everything except these inner classes?

like image 956
drmuelr Avatar asked Jan 12 '15 22:01

drmuelr


People also ask

Can we create our own immutable class?

In Java, when we create an object of an immutable class, we cannot change its value. For example, String is an immutable class. Hence, we cannot change the content of a string once created. Besides, we can also create our own custom immutable classes.

Can you create an immutable object that contains a mutable object?

If you want to encapsulate a mutable object into an immutable one, then you need to: Create a copy of the mutable object (i.e. via copy constructor, cloning, serialization/deserialization, etc.); never store the reference to the original mutable object. Never return the mutable object.


1 Answers

Is there a way to only allow inner classes to extend and implement the outer, abstract class?

Yes, make the constructor of the outer class private.

Example:

abstract class MyAbstractClass {     int i; // some property     private MyAbstractClass(int i) {         this.i = i;     }      public static class InnerConcrete extends MyAbstractClass {         int j; // some other property         public InnerConcrete(int i, int j) {             super(i);             this.j = j;         }     } } 

I don't think I've ever come across this approach. A factory pattern may be more flexible and allows you split the otherwise potentially large class into several files. Package access level of the abstract class may perhaps also be sufficient.

like image 159
aioobe Avatar answered Dec 08 '22 13:12

aioobe