Понимание наследования и абстрактных классов в Java - PullRequest
2 голосов
/ 11 декабря 2010

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

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

Скажем, у меня есть классное животное и классы кошка и собака, которые расширяют животное.У кошки, животного и собаки есть метод speak (), который для кошки печатает «мяу» и для собаки печатает «гав» и для животного «не могу говорить».

Хорошо, наконец, вот мой вопрос.Что именно происходит, если a make c (c) и затем запустить Animal a = c ;?Что произойдет, если я запускаю a.speak () ;?Какой метод разговора называется?Что именно произошло, когда я изменил такие типы?У меня когда-нибудь будет реальная причина использовать это?

Что касается абстрактных методов, мой вопрос в том, в чем именно их смысл?В примерах, которые я видел, они были помещены в суперклассы, а классы под ними определяют точное поведение.Помещение абстрактного метода в суперкласс требует того, чтобы все классы под ним реализовывали его?

Спасибо за вашу помощь!

Ответы [ 5 ]

3 голосов
/ 11 декабря 2010

Что именно произойдет, если сделать кошку (с), а затем запустить Animal a = c ;?Что произойдет, если я запускаю a.speak () ;?Какой метод разговора называется?Что именно произошло, когда я изменил такие типы?У меня когда-нибудь будет реальная причина использовать это?

Всегда метод реального класса, например, в данном случае, speak() метод кошки.

Что касается абстрактных методов, мой вопрос заключается в том, какой именно смысл их иметь?

Они удостоверяются, что, например, у каждого животного есть метод walk(), который вы можете вызватьна каждом животном.Это гарантия того, что «у каждого Animal объекта есть этот метод, вам не нужно об этом заботиться».

В примерах, которые я видел, они были помещены в суперклассыи классы под ними определяют точное поведение.Помещение абстрактного метода в суперкласс требует того, чтобы все классы под ним реализовывали его?

Чтобы реализовать его или быть абстрактным тоже, да.

2 голосов
/ 11 декабря 2010

Cat c = новый Cat (); Животное а = с; a.speak () напечатает мяу.

пожалуйста, отметьте полиморфизм Java out.

об абстрактном классе:

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

JLS, раздел 5.2 объясняет, почему Cat назначается на Animal. (Обратите внимание, что Animal не может быть неявно назначен на Cat, поскольку Cat является «более конкретным» видом; Cat является подтипом Animal, а Animal является супертипом Cat)

Присвоение значения ссылочного типа времени компиляции S (источник) переменной ссылочного типа времени компиляции T (цель) проверяется следующим образом:

  • Если S является типом класса:
    • Если T является типом класса, то S должен быть того же класса, что и T, либо S должен быть подклассом T, либо возникает ошибка времени компиляции.
    • Если T является типом интерфейса, то S должен реализовать интерфейс T, иначе произойдет ошибка времени компиляции.
    • Если T является типом массива, то возникает ошибка времени компиляции.
  • Если S - это тип интерфейса:
    • Если T является типом класса, то T должно быть Object, иначе произойдет ошибка времени компиляции.
    • Если T является типом интерфейса, то T должен быть либо тем же интерфейсом, что и S, либо суперинтерфейсом S, либо возникает ошибка времени компиляции.
    • Если T является типом массива, то возникает ошибка времени компиляции.
  • Если S является массивом типа SC [], то есть массивом компонентов типа SC:

[для краткости опущено]

1 голос
/ 11 декабря 2010

Скажем, у меня есть классное животное и классы кошка и собака, которые распространяют животное. У кошки, животного и собаки есть метод speak (), который для кошки печатает «мяу», а для собаки - «гав» и для животного «не могу говорить».

Хорошо, наконец, вот мой вопрос. Что именно происходит, если сделать кошку (c) и запустить Animal a = c;? Что произойдет, если я бегу a.speak();? Какой метод speak() вызывается? Что именно произошло, когда я изменил такие типы? У меня когда-нибудь будет реальная причина использовать это?

Объекты в Java точно знают, какого типа они были созданы; фактически это скрытое поле (которое вы можете получить с помощью метода Object.getClass()). Более того, все нестатические методы разрешения начинаются с определений методов наиболее специфического класса и переходят к наиболее универсальному классу (Object); поскольку в Java существует только одно наследование реализации, это простой поиск. Cat знает, что это подтип Animal, который является подтипом Object, а c знает, что это Cat независимо от типа переменной.

Когда вы делаете присваивание, компилятор проверяет, является ли известный тип присваиваемого значения типом, присваиваемым или одному из его подтипов . Если это так, назначение работает. Если это не так, вам понадобится явное приведение (которое вставляет правильную проверку типов во время выполнения; приведение не может сломать систему типов Java, они могут просто сделать это уродливым). Это не меняет того факта, что поиск метода все еще выполняется динамически, и объект все еще знает, какой это тип; все, что делает программа, это пренебрежение некоторой информацией. Если вы знаете C ++, то думайте, что в Java есть только виртуальные методы (и статические методы), и очень просто обрабатывать запросы в vtables, потому что нет проблем с наследованием алмазов или другими злыми случаями.

При работе с реализациями интерфейса это почти то же самое, за исключением того, что выполняется более сложный поиск (т. Е. Сначала просматривается индекс в vtable, а затем продолжается, как и раньше). Однако наличие объекта, реализующего интерфейс, означает, что должен существовать некоторый класс, который полностью реализует интерфейс, и к этому моменту все снова относительно просто. И помните, все действительно сложные вещи делаются во время компиляции; во время выполнения все относительно просто во всех случаях.

Итак, вы воспользуетесь этим? Ну, вы должны (и вам действительно будет очень трудно избежать в реальном коде). Это хороший стиль, чтобы думать о контракте, определяемом интерфейсом или суперклассом, когда подтипы подчиняются контракту, и вызывающая сторона не должна знать о деталях. Библиотеки Java используют это очень интенсивно, особенно потому, что видимость деталей типа контракта и его выполнение могут быть разными. Все, что клиентский код знает, это то, что объект подчиняется договору, что он имеет данный тип.

0 голосов
/ 11 декабря 2010

Насколько я понимаю, вы используете интерфейсы для разделения вашего кода.Вы хотите программировать с использованием интерфейсов, а не реализаций: Что значит «программировать на интерфейс»? .Вы бы использовали абстрактный класс для реализации функциональности, которая является тривиальной для всех реализующих классов, поэтому вам не нужно писать ее во всех реализующих классах.

0 голосов
/ 11 декабря 2010

В зависимости от вашего опыта, C ++ или Java могут запутаться.

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

В Java все методы в основном виртуальные, что означает, что методы Java всегда ищутся во время выполнения, процесс называется Полиморфизм времени выполнения

Выгода от этого примерно такая

class Animal{
    public void type(){
        System.out.println("animal");

    }
}

class Dog extends Animal{
    public void type(){
        System.out.println("dog");
    }
}

class Cat extends Animal{
    public void type(){
        System.out.println("cat");
    }
}

public class Driver{
    public static void main(String[] args){
        Animal[] animals = new Animal[3];
        animals[0] = new Animal();
        animals[1] = new Dog();
        animals[2] = new Cat();

        for(Animal animal: animals){
            animal.type();
        }
    }
}

Это выведет

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