java - tipos - ¿Cómo se puede crear una clase abstracta, inmutable?
objeto inmutable java (2)
Aquí está la versión corta. En primer lugar, quiero que mi clase sea inmutable. Sé que una clase no puede ser abstracta y final. Lo que pregunto es: ¿hay una manera de permitir que solo las clases internas extiendan e implementen la clase externa y abstracta? Puede que este no sea el mejor método para alcanzar mis objetivos inmutables, por lo que si alguien tiene un mejor diseño, me encantaría escucharlo.
Estoy escribiendo una clase para operaciones vectoriales, como en física e ingeniería, no en el sentido de la programación. (También soy consciente de que JScience tiene un paquete para este tipo de cosas. Quiero escribir el mío y mantenerlo simple).
Me gusta el patrón utilizado en el paquete de geometría de Java, en el que, por ejemplo, un Line2D
se puede crear utilizando uno de los dos niveles de precisión: flotante o doble.
public abstract class Line2D {
public static class Float extends Line2D { /* Implementation */ }
public static class Double extends Line2D { /* Implementation */ }
}
Esta es una característica que realmente me gustaría incorporar y expandir en mi clase, así que creé lo siguiente:
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
}
Obviamente, Vector2D.Integer
, Vector2D.Float
y Vector2D.Double
son finales. ¿Hay alguna manera de hacer Vector2D
final para todo excepto para estas clases internas?
¿Hay una manera de permitir que solo las clases internas extiendan e implementen la clase externa y abstracta?
Optaría por otra alternativa: hacer que sus clases abstractas no sean públicas y solo hacer públicas las clases de implementación final
. Este es el caso de AbstractStringBuilder
, que pertenece al paquete java.lang
, es abstract
y no public
, y se implementa mediante las clases StringBuilder
y StringBuffer
, que son public final
.
Aquí está el código fuente relevante de estas clases:
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...
}
¿Hay una manera de permitir que solo las clases internas extiendan e implementen la clase externa y abstracta?
Sí, hacer que el constructor de la clase externa sea privado.
Ejemplo:
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;
}
}
}
No creo que haya encontrado este enfoque. Un patrón de fábrica puede ser más flexible y le permite dividir la clase potencialmente grande en varios archivos. El nivel de acceso al paquete de la clase abstracta quizás también sea suficiente.