Подтвердить что ты не робот

Как создать абстрактный, неизменный класс?

Здесь короткая версия. Прежде всего: я хочу, чтобы мой класс был неизменным. Я знаю, что класс не может быть абстрактным и окончательным. Я спрашиваю: есть ли способ разрешить внутренним классам расширять и реализовывать внешний абстрактный класс?. Это может быть не лучший метод для достижения моих неизменных целей, поэтому, если кто-то имеет лучший дизайн, я бы с удовольствием его услышал.

Я пишу класс для векторных операций - как в физике, так и в технике, а не в смысле программирования. (Я также знаю, что 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 для всех, кроме этих внутренних классов?

4b9b3361

Ответ 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...
}