Как создать абстрактный, неизменный класс?
Здесь короткая версия. Прежде всего: я хочу, чтобы мой класс был неизменным. Я знаю, что класс не может быть абстрактным и окончательным. Я спрашиваю: есть ли способ разрешить внутренним классам расширять и реализовывать внешний абстрактный класс?. Это может быть не лучший метод для достижения моих неизменных целей, поэтому, если кто-то имеет лучший дизайн, я бы с удовольствием его услышал.
Я пишу класс для векторных операций - как в физике, так и в технике, а не в смысле программирования. (Я также знаю, что JScience имеет пакет для такого рода вещей. Я хочу написать свой собственный и сохранить его простым.)
Мне нравится шаблон, используемый в пакете геометрии Java, где, например, Line2D
может быть создан с использованием одного из двух уровней точности: float или double.
public abstract class Line2D {
public static class Float extends Line2D { /* Implementation */ }
public static class Double extends Line2D { /* Implementation */ }
}
Это функция, которую я бы хотел включить и расширить в своем классе, поэтому я создал следующее:
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
}
Очевидно, что Vector2D.Integer
, Vector2D.Float
и Vector2D.Double
являются окончательными. Есть ли способ сделать Vector2D
final для всех, кроме этих внутренних классов?
Ответы
Ответ 1
Есть ли способ разрешить внутренним классам расширять и реализовывать внешний абстрактный класс?
Да, создайте конструктор внешнего класса private.
Пример:
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;
}
}
}
Я не думаю, что когда-либо сталкивался с этим подходом. Шаблон factory может быть более гибким и позволяет разбить потенциально большой класс в несколько файлов. Возможно, также достаточен уровень доступа к пакетам абстрактного класса.
Ответ 2
Есть ли способ разрешить внутренним классам расширять и реализовывать внешний абстрактный класс?
Я бы выбрал другую альтернативу: сделайте ваши абстрактные классы непубличными и публикуйте только классы реализации final
. Это относится к AbstractStringBuilder
, который относится к пакету java.lang
, является abstract
и не public
, и он реализуется классами StringBuilder
и StringBuffer
, которые являются public final
.
Здесь соответствующий исходный код этих классов:
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...
}