Java-массив объектов и наследования - PullRequest
2 голосов
/ 09 ноября 2010

У меня есть 3 класса, MainClass с основным методом, один абстрактный класс с именем AbstractClass и Subclass, который должен быть расширен с помощью AbstractClass.

Массив объектов создается в методе main из типа AbstractClass, содержащего 1 член. Затем я инициализирую этот 1 элемент массива как тип Subclass (это нормально?). Проблема в том, что я не могу добраться до метода getDataToExport () созданного объекта (массив [0]). Я подозреваю, что проблема возникает, потому что массив является типом AbstractClass ... И вопрос: это вообще возможно сделать? То, что я пытаюсь сделать, это использовать массив типа AbstractClass и заполнить его объектами, сделанными из разных подклассов (в этом коде это просто one-> Subclass), расширенных с помощью AbstractClass, но я не могу добраться до методов этих подклассов.

основной класс с методом main

public class MainClass {

    public static void main() {

        AbstractClass array[]=new AbstractClass[1];
        array[0]= new Subclass(); // is this even allowed?
        System.out.println(array[0].getDataToExport()); // Problem!

    }

}

абстрактный класс

public abstract class AbstractClass {

}

Подкласс, расширяющий AbstractClass

public class Subclass extends AbstractClass {

    private int dataToExport;

    public Subclass(){
        this.dataToExport=2;
    }

    public int getDataToExport() {
        return dataToExport;
    }   

}

Ответы [ 5 ]

5 голосов
/ 09 ноября 2010
AbstractClass array[]=new AbstractClass[1];
array[0]= new Subclass(); // is this even allowed?

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

Единственная реальная причина для создания записей массива типа AbstractClass была бы, если вы хотите взаимодействовать только с членами, определенными в этом классе. Так, например, в этом случае вы, вероятно, захотите определить getDataToExport как абстрактный метод в абстрактном классе:

public abstract class AbstractClass {
    public abstract int getDataToExport();
}

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

Так, например:

public class MainClass {

    public static void main() {

        NiftyThingy array[]=new NiftyThingy[1];
        array[0]= new NiftyThingyImplementation();
        System.out.println(array[0].getDataToExport());

    }

}

, где

public interface NiftyThingy {

    public int getDataToExport();

}

и

public class NiftyThingyImplementation implements NiftyThingy {

    public int getDataToExport() {
        return /* ... the data ... */;
    }

}
2 голосов
/ 09 ноября 2010

Вы должны объявить getDataToExport () как абстрактный метод в AbstractClass.

0 голосов
/ 09 ноября 2010
  AbstractClass array[]=new AbstractClass[1];
  array[0]= new Subclass(); // is this even allowed?

Действительно действительно, поскольку SubClass является производным классом AbstractClass. Причина, по которой

System.out.println(array[0].getDataToExport());

терпит неудачу, потому что компилятор не может найти метод AbstractClass.getDataToExport(). Только SubClass имеет метод, а не его родитель.

Есть несколько способов решить эту проблему:

Добавить абстрактный метод getDataToExport к AbstractClass примерно так:

public abstract class AbstractClass {
    public abstract int getDataToExport();
}

OR, Typecast ваша переменная к ее производному (конкретному) классу, который имеет метод getDataToExport(), например:

if (array[0] instanceof SubClass) {
    System.out.println(((SubClass)array[0]).getDataToExport());
}

оператор instanceof просто утверждает, что атрибут относится к классу X (где X равен SubClass).

0 голосов
/ 09 ноября 2010

Да, все это прекрасно.Единственный пропущенный шаг - вам нужно привести экземпляр объекта к типу, который имеет нужный метод.Обычный способ сделать это:

AbstractClass ac = array[0];
if (ac instanceof Subclass) {
  System.out.println(((Subclass)ac).getDataToExport()); // No problem!
}

Однако вы можете подумать о том, чтобы сделать это по-другому.Например, реализуйте версию getDataToExport по умолчанию в абстрактном классе, который возвращает ноль.Таким образом, вам не нужно выполнять приведение или тест instanceof.

0 голосов
/ 09 ноября 2010

Вы не сможете получить его, потому что вы объявляете массив AbstractClass, чтобы увидеть их, у вас есть два варианта

  • Объявите общие методы, которые вы будете использовать в абстрактном классе, и объявите их абстрактными. Переопределите эти методы в подклассах. Например:

    открытый абстрактный класс AbstractClass { public abstract int getDataToExport (); }

И каждый подкласс должен будет переопределить этот метод или должен быть объявлен абстрактным.

  • Создать массив подкласса:

    массив подклассов [] = новый подкласс [1]; array [0] = new Subclass (); System.out.println (массив [0] .getDataToExport ());

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...