Проблема наивного наследования - Java - PullRequest
4 голосов
/ 10 сентября 2011

G'day люди,

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

enter image description here

B расширяет A, код, который я написал, как показано ниже,

Класс A

public class A{
    private int pos = 0;
    public A(){
        this.pos = 12;
    }
    public int getPos(){
        return this.pos;
    }
}

Класс B

public class B extends A{
    int spec = 15;
    public B(){
        super();
    }
    public int getSpec(){
        return this.spec;
    }
}

И у меня есть еще один класс для тестирования, который поставит нас на мой вопрос.

Class Test

import java.util.*;
public class Test{
    public static void main(String[] args){
        B a = new B();
        ArrayList<A> c = new ArrayList<A>();
        c.add(a);
        System.out.println(c.get(0).getPos());
        System.out.println(c.get(0).getSpec());
    }
}

Вопрос: Сейчас я создаю экземпляр B, что означает, что я могу получить доступ к методу моего родительского класса getPos() и к собственному Bметод getSpec().Но если я создаю ArrayList с типом A (... B тоже относится к типу A, поскольку он расширяет A ...) и добавляю экземпляр моего B, он теряет способность обращаться к своему собственному методу.Что я делаю неправильно?Приводит ли реализация ArrayList мой B к A внутри?

Примечание. Основное понимание наследования заключается в том, что родитель не может получить доступ к дочернему методу, за исключением случаев, когда он защищен.Но Child может получить доступ к методу своего родительского класса.

Ответы [ 3 ]

4 голосов
/ 10 сентября 2011

Приводит ли реализация ArrayList мой B к A внутри?

Нет.Там нет "внутреннего литья". Вы, программист, сказали компилятору, что это список A.

У вас объявлен List как List<A>, который вы можетечитать как "список A" .Поскольку все B равны A, вы можете добавить любой B к List<A>.Однако при получении вы гарантированно получите только A, а не B - потому что это List<A>, помните - поэтому компилятор обрабатывает все , что выходит из спискакак A, даже если (во время выполнения) это экземпляр B.

4 голосов
/ 10 сентября 2011

Там нет кастинга.То, что вы делаете, ничем не отличается от этого:

A bAsA = new B():

Хотя объект, на который ссылается bAsA, действительно является объектом B, он удерживается переменной A, и поэтому доступны только методы A (если вы явноприведите его как переменную B).

Поскольку ваш ArrayList является ArrayList для A, каждый элемент в ArrayList обрабатывается как переменная A, и доступны только методы A.

3 голосов
/ 10 сентября 2011

В дополнение к ответам, предоставленным @ Matt Ball и @ Hovercraft Full Of Eels , вы можете избежать явного приведения объявив методы, реализованные подклассом , как abstract методы в суперклассе .

public abstract class A{
    .
    .
    public abstract int getSpec();
}

Edit-

Как упомянуто @ Kublai Khan , необходимо затем создать суперкласс и abstract class.

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