Reputation: 1125
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?
Upvotes: 22
Views: 4145
Reputation: 421090
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.
Upvotes: 25
Reputation: 85779
Is there a way to only allow inner classes to extend and implement the outer, abstract class?
I would opt for another alternative: make your abstract classes non-public and only make public the final
implementation classes. This is the case of AbstractStringBuilder
, which belongs to java.lang
package, is abstract
and non-public
, and it's implemented by StringBuilder
and StringBuffer
classes, which are public final
.
Here's the relevant source code of these classes:
abstract class AbstractStringBuilder implements Appendable, CharSequence {
//implementation details...
}
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence {
//implementation details...
}
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence {
//implementation details...
}
Upvotes: 10