2015-11-08 4 views
1

Для назначения у меня есть ArrayList типа «Reference». Ссылка является родительским классом класса «Книга» и класса «Журнал». Если мне разрешено добавлять объекты типа «Книга» и «Журнал» к Arraylist, почему я получаю сообщение об ошибке, если я хочу получить доступ к методам Book and Journal через следующий код?Доступ к методу подкласса из arraylist суперкласса

  ArrayList.get([someindex]).someBookorJournalMethod() 

Самого ArrayList является родительским классом, и методы, которые я хочу получить доступ, определяются только для каждой книги или любого журнала.

EDIT: Вот код

public class Books extends Reference{ 

    private String Authors; 
    private String Publishers; 


     public Books(String CallNum, String Author, String Title, String Publisher, int year,String type) 
     { 

      super(CallNum,Title,year,type); 

      Authors= Author; 
      Publishers=Publisher; 
     } 

public String getAuthor() 
{ 
    return Authors; 
} 



public class LibrarySearch { 


     private ArrayList<Reference> Library; 


     public LibrarySearch() 
     { 
      Library = new ArrayList<Reference>(100); 
     } 


     public outputLibrary(){ 

     for (int i = 0 ; i < Library.size(); i+++) 
     { 
     if (Library.get(i).getType().equals("Book")) 
     { 
      System.out.println("Type:book\n" + "Call Number:" + Library.get(i).getCallNumber() +"\n" + "Authors:" + Library.get(i).getAuthors();) 
     } 
    } 

} 

IntelliJ испытывает проблемы с линией Library.get (я) .getAuthors(), потому что это метод специфичны для книг. Как я могу это решить?

+0

Вместо 'if (Library.get (i) .getType(). Equals (" Book "))' вы должны делать 'if (Library.get (i) instanceof Book)'. Но тогда лучше не снижать, а вместо этого применять метод toString, как предлагает один из приведенных ниже комментариев. –

ответ

3

Потому что, когда вы укажете тип переменной, вы можете использовать только методы, определенные для этого типа. Например, если у вас есть

public class A { 
    public void methodA() { 
    System.out.println("A"); 
    } 
} 

public class B extends A { 
    public void methodB() { 
    System.out.println("B"); 
    } 
} 

public class Main { 
    public static void main(String[] args) { 
    A ab = new B(); 
    ab.methodB(); 
    } 
} 

Это не будет компилироваться, так как тип, определенный для переменного ab является A и только видимые методами являются те, которые определены в A.

В вашем случае вы можете просто добавить пустой метод в Reference (если вы не хотите, чтобы сделать класс аннотацию):

public void someBookorJournalMethod() {} 

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

Однако важно отметить, что оба подхода обычно являются плохими методами, и их следует избегать. Если не существует смысла создавать объекты Reference, чем сделать класс abstract и определить someBookorJournalMethod в качестве абстрактного метода. В вашем коде вы, скорее всего, используете наследование неправильно.

+0

Я могу уйти с пустой реализацией для метода суперкласса без проблем компиляции? –

+0

Да, если это 'void'. –

+0

, но тогда, если реализация в подклассах имеет непустые возвращаемые типы, это не вызовет ошибку? –

0

Вы не можете получить доступ к методу подкласса из суперкласса. Поэтому вам нужно будет бросить книгу или журнал.

Reference r =ArrayList.get([someindex]); 
if (r instanceof Book) { 
    ((Book) r).someBookMethod(); 
} else if (r instanceof Journal) { 
    ((Journal) r).someJournalMethod(); 
} 
Смежные вопросы