Форум программистов, компьютерный форум, киберфорум
Наши страницы
Java SE (J2SE)
Войти
Регистрация
Восстановить пароль
 
farta
0 / 0 / 2
Регистрация: 14.10.2015
Сообщений: 48
#1

Для чего нужен абстрактные классы/интерфейсы? - Java SE

13.04.2016, 22:47. Просмотров 1701. Ответов 18
Метки нет (Все метки)

Для чего нужны абстрактные классы/интерфейсы? Уже устал лазить по форумам, везде довольно размытые ответы. Я понимаю, что абстрактный класс и интерфейс это разные вещи, но вообщем для чего это применяется? В чем смысл пустого метода/поля , который все равно придется реализовать? К примеру, интерфейс гарантирует, что мы реализуем метод, но что мешает просто написать этот метод в классе и всё? Или же абстрактный класс, часто приводится пример с классом "Фигура", и его наследники "Квадрат", "Треугольник" и тд. Но все равно во всех наследниках придется писать свою реализацию метода. Возможно вопрос глупый, но не пойму я, в чем такая польза метода "пустышки", который можно и написать с нуля, не переопределяя. Надеюсь, что раскрою сей секрет, а то мозги уже кипят...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
13.04.2016, 22:47
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Для чего нужен абстрактные классы/интерфейсы? (Java SE):

Реализовать абстрактные классы или интерфейсы, а также наследование и полиморфизм для классов: interface Mobil
Реализовать абстрактные классы или интерфейсы, а также наследование и...

Абстрактные классы и Интерфейсы
Помогите пожалуйста решить задание)))) Цель выполнения задания: реализовать...

Абстрактные классы и интерфейсы
Помогите пожалуйста!!!Срочно!!! Задание: Создать абстрактный класс Norm с...

Абстрактные классы и интерфейсы
Уважаемые, помогите новичку разобраться с абстрактными классами и...

Зачем нужны интерфейсы когда есть абстрактные классы?
Собсно говоря сабж. Не пойму зачем нужны интерфейсы когда то-же самое можно...

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

18
Fulcrum_013
Заблокирован
13.04.2016, 22:56 #2
На самом деле нет никакой пустышки. Есть команда зарезервировать место под метод в VMT. А реализовав метод у квадрата и треугольник, можем как квадрат так и треугольник привести к фигуре и вызвать этот метод. При этом у рожденного квадратом вызовется метод квадрата а у рожденного треугольником вызовется метод треугольника. Т.е. можем засунуть к примеру в один массив фигур и квадраты и треугольники, и всем элементам массива по очереди вызвать к примеру метод отрисовки. При этом квадраты отрисуются квадратами а треугольники треугольниками.
0
farta
0 / 0 / 2
Регистрация: 14.10.2015
Сообщений: 48
13.04.2016, 23:04  [ТС] #3
Fulcrum_013, все равно не пойму, в чем проблема просто прописать метод у квадрата и треугольника без наследования? Результат же не изменится
0
Fulcrum_013
Заблокирован
13.04.2016, 23:32 #4
Цитата Сообщение от farta Посмотреть сообщение
Результат же не изменится
А теперь попробуй этот неизменившийся результат запихнуть в один массив.
0
korvin_
2092 / 1583 / 307
Регистрация: 28.04.2012
Сообщений: 5,707
13.04.2016, 23:39 #5
Цитата Сообщение от farta Посмотреть сообщение
все равно не пойму, в чем проблема просто прописать метод у квадрата и треугольника без наследования? Результат же не изменится
С интерфейсом:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
interface Figure {
 
    double square();
}
 
final class Rectangle implements Figure {
 
    private final double width;
    private final double height;
 
    public Rectangle(final double width, final double height) {
        this.width = width;
        this.height = height;
    }
 
    @Override
    public double square() {
        return width * height;
    }
 
    @Override
    public String toString() {
        return String.format("%s{ width = %f ; height = %f }",
                getClass().getSimpleName(), width, height);
    }
}
 
final class Circle implements Figure {
 
    private final double radius;
 
    public Circle(final double radius) {
        this.radius = radius;
    }
 
    @Override
    public double square() {
        return Math.PI * radius * radius;
    }
 
    @Override
    public String toString() {
        return String.format("%s{ radius = %f }",
                getClass().getSimpleName(), radius);
    }
}
 
public class Main {
 
    private static void printSquares(final Figure... figures) {
        Stream.of(figures).forEach(f ->
                System.out.printf("%s square = %f%n", f.toString(), f.square()));
    }
 
    public static void main (String[] args) throws java.lang.Exception {
        printSquares(new Rectangle(3, 4), new Circle(2));
    }
}
Bash
1
2
Rectangle{ width = 3.000000 ; height = 4.000000 } square = 12.000000
Circle{ radius = 2.000000 } square = 12.566371
http://ideone.com/3ehYgL

Без интерфейса:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
final class Rectangle {
 
    private final double width;
    private final double height;
 
    public Rectangle(final double width, final double height) {
        this.width = width;
        this.height = height;
    }
 
    public double square() {
        return width * height;
    }
 
    @Override
    public String toString() {
        return String.format("%s{ width = %f ; height = %f }",
                getClass().getSimpleName(), width, height);
    }
}
 
final class Circle {
 
    private final double radius;
 
    public Circle(final double radius) {
        this.radius = radius;
    }
 
    public double square() {
        return Math.PI * radius * radius;
    }
 
    @Override
    public String toString() {
        return String.format("%s{ radius = %f }",
                getClass().getSimpleName(), radius);
    }
}
 
public class Main {
 
    private static void printSquares(final ?... figures) {
        Stream.of(figures).forEach(f ->
                System.out.printf("%s square = %f%n", f.toString(), f.square()));
    }
 
    public static void main (String[] args) throws java.lang.Exception {
        printSquares(new Rectangle(3, 4), new Circle(2));
    }
}
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Main.java:51: error: illegal start of type
    private static void printSquares(final ?... figures) {
                                           ^
Main.java:51: error: ')' expected
    private static void printSquares(final ?... figures) {
                                            ^
Main.java:51: error: ';' expected
    private static void printSquares(final ?... figures) {
                                               ^
Main.java:51: error: illegal start of type
    private static void printSquares(final ?... figures) {
                                                       ^
Main.java:51: error: <identifier> expected
    private static void printSquares(final ?... figures) {
                                                        ^
Main.java:51: error: ';' expected
    private static void printSquares(final ?... figures) {
                                                          ^
Main.java:52: error: illegal start of type
        Stream.of(figures).forEach(f ->
              ^
Main.java:52: error: <identifier> expected
        Stream.of(figures).forEach(f ->
                         ^
Main.java:52: error: ';' expected
        Stream.of(figures).forEach(f ->
                          ^
Main.java:56: error: class, interface, or enum expected
    public static void main (String[] args) throws java.lang.Exception {
                  ^
Main.java:58: error: class, interface, or enum expected
    }
    ^
11 errors
http://ideone.com/kBNyUC


Сам догадаешься, в чём разница?
0
farta
0 / 0 / 2
Регистрация: 14.10.2015
Сообщений: 48
13.04.2016, 23:48  [ТС] #6
korvin_, эмммм... Честно говоря, я не понял, каким образом лишь переоопределенный метод интерфейса делает прогу рабочей, а если писать их ручками, то начинается дикая куча ошибок... Конкретней, если можно, новичок же:3
0
MLPMan
Кандёхаем веселее!
287 / 291 / 75
Регистрация: 02.10.2012
Сообщений: 2,028
14.04.2016, 00:12 #7
farta, с интерфейсами можно непосредственно обращаться к элементам, как к Figure, а если без, то только как к Object-ам, и перед каждым действием придётся проверять типы (instanceof), а затем приводить к нужному. Полиморфизм жи есть.
0
Fulcrum_013
Заблокирован
14.04.2016, 00:12 #8
Цитата Сообщение от farta Посмотреть сообщение
Честно говоря, я не понял, каким образом лишь переоопределенный метод интерфейса делает прогу рабочей, а если писать их ручками, то начинается дикая куча ошибок..
Да все очень просто. Когда два класса порождены от одного интерфейса они гарантированно имеют набор методов определенный в интерфейсе. Тогда указатели на эти методы для каждого класса можно сохранить в одинаковых таблицах а в каждый класс положить указатель на эти таблицы. При вызове берется указатель на таблицу, из нее выбирается указатель на метод и вызывается. При этом тупо по номеру. А под каким номером что в таблице лежит и задается списком методов в базовом абстрактном классе.
Если же базового класса нет, то эти два класса ничем между собой не связаны кроме твоего воображения. По большому счету этот абстрактный класс и нужен для того чтобы об этой воображаемой тобой (абстрактной) связи сообщить компилятору.
0
korvin_
2092 / 1583 / 307
Регистрация: 28.04.2012
Сообщений: 5,707
14.04.2016, 00:16 #9
Цитата Сообщение от farta Посмотреть сообщение
эмммм... Честно говоря, я не понял, каким образом лишь переоопределенный метод интерфейса делает прогу рабочей, а если писать их ручками, то начинается дикая куча ошибок... Конкретней, если можно, новичок же:3
Попробуй сделать нерабочую прогу рабочей.
0
farta
0 / 0 / 2
Регистрация: 14.10.2015
Сообщений: 48
14.04.2016, 07:52  [ТС] #10
Fulcrum_013, Так, если я правильно понял, то абстрактный класс нужен для того, чтобы создавать исключительно родственные классы, интерфейс же позволяет сделать "полу родственными"(типо появляется возможность множественного наследования) даже два совершенно разных класса, повязав их одним общим методом, и при вызове этого метода будет проявляться полиморфизм? Тогда еще остается вопрос, что же компилятор не устраивает, не пойму
0
KEKCoGEN
Эксперт Java
2033 / 1908 / 491
Регистрация: 28.12.2010
Сообщений: 7,651
14.04.2016, 08:17 #11
Цитата Сообщение от farta Посмотреть сообщение
интерфейс же позволяет сделать "полу родственными"
интерфейс это контракт работы классов с окружением. Их удобно использовать т.к это уменьшает общую связанность программы. Пока примите это как данное. Реальзую пользу вы поймете когда начнете учить всякие j2ee фреймворки

Цитата Сообщение от farta Посмотреть сообщение
Тогда еще остается вопрос, что же компилятор не устраивает
То что вы говорите что вы можете сами определить нужные методы в двух классах и вы как бы обещаете компилятору типа "я сам напишу эти методы чесслово и когда их надо будет вызвать, они там будут", однако компилятор вашему слову не верит. Вдруг вы его обманываете и поэтому требует чтобы вы определили интерфейс или абстрактный класс чтобы быть уверенным что нужный метод правда будет во всех нужных классах. Это если по простому. Если по-сложному, смотрите ответ Fulcrum_013. Он объяснил как это работает с точки зрения внутреннего устройства.
0
Fulcrum_013
Заблокирован
14.04.2016, 09:46 #12
Цитата Сообщение от farta Посмотреть сообщение
ак, если я правильно понял, то абстрактный класс нужен для того, чтобы создавать исключительно родственные классы, интерфейс же позволяет сделать "полу родственными"
Интерфейс это просто список виртуальных методов, и он не может иметь ни реализации этих методов, ни невиртуальных методов. Абстрактный же класс может иметь как невиртуальные методы, так и иметь реализацию части виртуальных методов. Пример - если объекты умеют двигаться, а позиция задается какой либо точкой, то метод задания позиции можно один раз реализовать в абстрактном базовом классе, оставив реализацию виртуальных (полиморфных) методов к примеру отрисовки вычисления площади и т.д. потомкам.

Добавлено через 1 минуту
Т.е. разница - у абстрактнонго класса часть методов не реализована. У интерфейса все методы не реализованы.
0
KEKCoGEN
Эксперт Java
2033 / 1908 / 491
Регистрация: 28.12.2010
Сообщений: 7,651
14.04.2016, 13:48 #13
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
У интерфейса все методы не реализованы.
это было так до выхода java 8. Начиная с 8 версии интерфейс может содержать дефолтную реализацию метода
0
Fulcrum_013
Заблокирован
14.04.2016, 13:54 #14
Цитата Сообщение от KEKCoGEN Посмотреть сообщение
может содержать дефолтную реализацию метода
Невиртуального или только виртуального? Если и невиртуального то разница с абстрактными классами вообще исчезла.
0
KEKCoGEN
Эксперт Java
2033 / 1908 / 491
Регистрация: 28.12.2010
Сообщений: 7,651
14.04.2016, 14:02 #15
Fulcrum_013, в джава нет ключевого слова virtual. В интерфейсе можно определить метод и ему можно дать дефолтную реализацию.
0
farta
0 / 0 / 2
Регистрация: 14.10.2015
Сообщений: 48
14.04.2016, 19:59  [ТС] #16
KEKCoGEN, ладно, спасибо, пока приму так, сколько же еще читать...

Добавлено через 1 минуту
Fulcrum_013, Это я понимаю, меня просто заботил вопрос, зачем такие сложности в интерфейсах с пустыми методами, если их всё равно придется реализовать

Добавлено через 19 минут
KEKCoGEN, и дабы не создавать лишних тем, хотел бы узнать, стоит ли читать "философия java", а то все пишут, что данное издание на русском устарело и тд и тп, а мне больше важно сам фундамент из теории заложить
0
Fulcrum_013
Заблокирован
14.04.2016, 23:09 #17
Цитата Сообщение от farta Посмотреть сообщение
Это я понимаю, меня просто заботил вопрос, зачем такие сложности в интерфейсах с пустыми методами, если их всё равно придется реализовать
Компилятор абсолютно ничего от твоих мыслях не знает пока ты ему их явно не напишешь джавой по (какой там у тебя цвет экрана?) цвету. И если ты задумал что у тебя есть какие то взаимосвязанные объекты методы которых ты потом собираешься реализовать, то чтобы компилятор понял что они взаимосвязаны, сначала нужно ему дать эту взаимосвязь (базовый абстрактный класс) и перечислить что у них общего - список методов который потом будет реализован в каждом потомке. Да кстати, точно так же как Java телепатическими способностями не обладают ни PHP ни С# ни Pascal ни даже С++
1
KEKCoGEN
Эксперт Java
2033 / 1908 / 491
Регистрация: 28.12.2010
Сообщений: 7,651
14.04.2016, 23:34 #18
Цитата Сообщение от farta Посмотреть сообщение
и дабы не создавать лишних тем
см. правила. Один вопрос - одна тема

Цитата Сообщение от farta Посмотреть сообщение
стоит ли читать "философия java"
без понятия. Книг не читал. Спросите в разделе Литература по Java
0
farta
0 / 0 / 2
Регистрация: 14.10.2015
Сообщений: 48
15.04.2016, 00:38  [ТС] #19
Fulcrum_013, спасибо, вроде что-то прояснилось более менее, для большего понимания нужно наверное больше практики, где придется применять это
0
15.04.2016, 00:38
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.04.2016, 00:38
Привет! Вот еще темы с решениями:

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

Абстрактные классы
Есть пример из учебника, все вроде правильно вдумчиво набил, но NetBeans выдает...

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

Абстрактные классы
Добрый день! Уважаемые коллеги, подскажите новичку. Если класс Cat расширяет...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru