Для проекта я написал следующий интерфейс:

public interface IManipulation {
    void applyManipulation (double value);
}

Поскольку я хотел бы заставить все реализующие классы использовать определенную сигнатуру конструктора, я подумал о том, чтобы изменить интерфейс на что-то вроде следующего абстрактного класса:

( изменить : я забыл, что абстрактный конструктор невозможно, поэтому я немного изменил "решение" ниже)

public abstract class Manipulation {
    private Signal signal;

    public Manipulation (Signal signal) {
        this.signal = signal;
    }

    public abstract void applyManipulation (double value);

    protected Signal getSignal () {
        return signal;
    }
}

Причина, по которой вы хотите принудительно использовать этот конструктор, заключается в том, что каждая имплантация должна иметь доступный экземпляр Signal. (и этот сигнал нельзя назначить)

Это веская причина заменить интерфейс абстрактным классом (и жить с ограничениями, которые с ним связаны), или есть какие-то другие потенциальные решения?

1
Michiel 25 Ноя 2016 в 14:54

3 ответа

Лучший ответ

Вместо абстрактного класса вы должны использовать для этой цели метод инициализации.

public interface MyInterface{
    public void init(YourParam p);
    //... other methods
}

В инициализации вы проверяете, если класс уже инициализирован, если да, просто вернитесь.

Таким образом, у вас все еще есть интерфейс, и вы можете расширяться от других классов. Вместо конструктора вы вызовете метод инициализации для своей инициализации

< Сильный > EDIT :

public interface IManipulation {
    void init(Signal s);
    void applyManipulation (double value);
}

Вы должны использовать только абстрактные классы, если у вас есть детали реализации, которые являются общими для всех подклассов. Для сигнатур методов используйте интерфейсы

1
Jarlik Stepsto 25 Ноя 2016 в 12:01

Вы можете сделать пустой конструктор приватным в абстрактном классе:

abstract class AbstractManipulation {
    private final Integer signal;

    private AbstractManipulation() {

        signal = null;
    }

    public AbstractManipulation (Integer signal) {
        this.signal = signal;
    }
}


class Manipulation extends AbstractManipulation {

    public Manipulation(Integer signal) {
        super(signal);
    }

    // Cannot redeclare
    //public Manipulation() {
    //}
}

Затем:

public static void main(String[] args) {


    // Will not work
    //Manipulation m = new Manipulation();

    // This one will
    Manipulation m = new Manipulation(1);
}
0
Alexey Soshin 25 Ноя 2016 в 12:05

Вы должны выбирать не по техническим причинам, а скорее по логике, т.е. абстрактный класс используется, когда у вас есть связь с подклассами, например, человек: ученик, учитель. Интерфейс используется, когда вы хотите наложить контракт на обслуживание для классов, которые могут не иметь отношения между ними.

0
andolsi zied 25 Ноя 2016 в 12:06