Как я могу вынудить Конструктора быть определенным во всем подклассе моего абстрактного класса

У меня есть абстрактный класс A, которые определяют абстрактные методы. Это означает, что, чтобы класс был instanciable, весь абстрактный метод должен быть реализован.

Я хотел бы, чтобы все мои подклассы реализовали конструктора с 2 ints как параметры.

Объявление конструктора побеждает мою цель, поскольку я хочу конструктора, определенного в подклассах, и я ничего не знаю о реализации. Кроме того, я не могу объявить конструктора, как являющегося абстрактным;

Существует ли способ сделать это?

Пример того, что я хочу:

Позволяет говорят, что я определяю API Матричного класса. В моей проблеме Матрица не может изменить их размеры.

Чтобы Матрица была создана, я должен обеспечить ее размер.

Следовательно, я хочу, чтобы все мои конструкторы предоставили конструктору размер в качестве параметра. Этот конструктор мотивирован проблемой, не беспокойством реализации. Реализация может сделать то, что она хочет с ними, при условии, что все семантические из методов сохранены.

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

64
задан dodecaplex 29 August 2016 в 12:49
поделиться

3 ответа

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

Более того, как вы говорите, вы ничего не знаете о реализации - так как же узнать, что для них уместно иметь конструктор, требующий двух целых чисел? Что, если одному из них также понадобится String? Или, возможно, имеет смысл использовать константу для одного из этих целых чисел.

Что здесь больше - почему вы хотите принудительно использовать конкретную сигнатуру конструктора для своих подклассов? (Как я уже сказал, на самом деле вы не можете сделать это, но если вы объясните, зачем вам это нужно, решение может появиться само.)

Один из вариантов - иметь отдельный интерфейс для фабрики:

interface MyClassFactory
{
    MyClass newInstance(int x, int y);
}

Тогда каждому из ваших конкретных подклассов MyClass также потребуется фабрика, которая знает, как построить экземпляр с двумя целыми числами. Однако это не очень удобно - и вам все равно придется создавать экземпляры самих фабрик. Опять же, какова здесь реальная ситуация?

53
ответ дан 24 November 2019 в 16:01
поделиться

Если вам нужно определить в вашем интерфейсе внутреннее представление, которое будут использовать реализующие классы, то вы просто делаете это неправильно. Прочтите, пожалуйста, о инкапсуляции и абстракции данных .

Если ваша абстрактная реализация полагается на определенные детали реализации, то они принадлежат этому абстрактному классу. Это означает, что абстрактный класс должен определять конструктор, который позволяет ему инициализировать внутреннее состояние, необходимое для работы абстрактных методов.

Как правило, конструкторы предназначены для создания экземпляра класса, предоставляя некоторые детали начального состояния этого экземпляра объекта. Это не означает, что создаваемый экземпляр должен копировать ссылку на каждый отдельный аргумент, как это часто бывает в большинстве программ, которые я вижу. Следовательно, даже если бы Java действительно предлагала конструкцию для принудительной реализации определенных сигнатур конструктора в подклассах, эти подклассы могли бы легко отбросить аргументы.

3
ответ дан 24 November 2019 в 16:01
поделиться

Вы можете попробовать следующее. Конструктор вызовет исключение, если реализующий класс не имеет конструктора с соответствующими аргументами.

Это глупо. Сравните ОК и Плохое. Оба класса одинаковы, за исключением того, что OK соответствует вашим требованиям и, таким образом, проходит проверки во время выполнения. Таким образом, выполнение требования способствует непродуктивной занятой работе.

Лучшим решением была бы какая-то фабрика.

abstract class RequiresConstructor
{
    RequiresConstructor( int x, int y ) throws NoSuchMethodException
    {
    super();
    System.out.println( this.getClass().getName() ) ;
    this.getClass(). getConstructor ( int.class , int.class ) ;
    }

    public static void main( String[] args ) throws NoSuchMethodException
    {
    Good good = new Good ( 0, 0 );
    OK ok = new OK ();
    Bad bad = new Bad ();
    }
}

class Good extends RequiresConstructor
{
    public Good( int x, int y ) throws NoSuchMethodException
    {
    super( x, y ) ;
    }
}

class OK extends RequiresConstructor
{
    public OK( int x, int y ) throws NoSuchMethodException
    {
    super( x, y ) ;
    throw new NoSuchMethodException() ;
    }

    public OK() throws NoSuchMethodException
    {
    super( 0, 0 ) ;
    }
}

class Bad extends RequiresConstructor
{
    public Bad() throws NoSuchMethodException
    {
    super( 0, 0 ) ;
    }
}
6
ответ дан 24 November 2019 в 16:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: