Каковы некоторые практические примеры абстрактных классов в Java?

На языке - / агностический платформой способ разговора, преобразовывающего из одного типа или класса другому, известен как [1 121] кастинг . Это верно для.NET также как Ваши первые четыре шоу строк:

object x;
int y;

x = 4;

y = ( int )x;

C и подобный языкам C (такие как C#) используют (newtype)somevar синтаксис для кастинга. В VB.NET, например, существуют явные встроенные функции для этого. Последняя строка была бы записана как:

y = CInt(x)

Или, для более составных типов:

y = CType(x, newtype)

, Где 'C', очевидно, короток для 'броска'.

.NET также имеет эти Convert() функция, как бы то ни было. Это не встроенная функция языка (в отличие от вышеупомянутых двух), а скорее одна из платформы. Это становится более ясным при использовании языка, который не обязательно используется вместе с.NET: у них все еще очень вероятно есть свои собственные средства кастинга, но это-.NET, которая добавляет Convert().

, Поскольку Matt говорит, различие в поведении - то, что Convert() является более явным. Вместо того, чтобы просто говорить компилятору рассматривать y как целочисленный эквивалент x, Вы конкретно говорите ему изменяться x таким способом, который подходит для целочисленного класса, тогда присваивают результат [1 110].

В Вашем особом случае, кастинг делает то, что называют, 'распаковывая', тогда как Convert() на самом деле получит целочисленное значение. Результат появится то же, но существуют тонкие различия лучше объяснены Keith.

17
задан Ravindra babu 8 November 2016 в 19:13
поделиться

9 ответов

Абстрактные классы - это «полуреализации» класса. Их можно частично реализовать с помощью некоторых общих функций, но оставьте часть реализации наследующим классам. У вас может быть абстрактный класс с именем Animal , в котором реализовано некоторое общее поведение / значения, такие как Age , Name , SetAge (...) . У вас также могут быть методы, которые не реализованы (они абстрактные ), очень похожие на интерфейс.

Интерфейсы - это просто контракты, которые определяют поведение, которое должно быть доступно для класса. У вас может быть такой интерфейс, как IWalker , для которого требуется общедоступный метод Walk () , но не указано, как он реализован.

9
ответ дан 30 November 2019 в 12:00
поделиться

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

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

5
ответ дан 30 November 2019 в 12:00
поделиться

Abstract Classes versus Interfaces

Unlike interfaces, abstract classes can contain fields that are not static and final, and they can contain implemented methods. Such abstract classes are similar to interfaces, except that they provide a partial implementation, leaving it to subclasses to complete the implementation. If an abstract class contains only abstract method declarations, it should be declared as an interface instead.

Multiple interfaces can be implemented by classes anywhere in the class hierarchy, whether or not they are related to one another in any way. Think of Comparable or Cloneable, for example.

By comparison, abstract classes are most commonly subclassed to share pieces of implementation. A single abstract class is subclassed by similar classes that have a lot in common (the implemented parts of the абстрактный класс), но также есть некоторые различия (абстрактные методы).

Пример абстрактного класса

В объектно-ориентированном приложении для рисования можно рисовать круги, прямоугольники, линии, кривые Безье и многое другое графические объекты. Эти объекты все иметь определенные состояния (например: положение, ориентация, цвет линии, цвет заливки) и поведения (для пример: moveTo, вращать, изменять размер, рисовать) в общем. Некоторые из этих состояний и поведение одинаково для всех графических объекты - например: положение, заливка цвет и moveTo. Другие требуют различные реализации - например, изменить размер или нарисовать. Все Графические объекты должен знать, как рисовать или изменять размер самих себя; они просто отличаются тем, как они это делают. Это идеальный ситуация для абстрактного суперкласса. Вы можете воспользоваться сходства и объявить все graphic objects to inherit from the same abstract parent object—for example, GraphicObject, as shown in the following figure.

Classes Rectangle, Line, Bezier, and Circle inherit from GraphicObject

Classes Rectangle, Line, Bezier, and Circle inherit from GraphicObject

[...]

Source: The Java™ Tutorials

5
ответ дан 30 November 2019 в 12:00
поделиться

http://java.sun.com/docs/books/tutorial/java/IandI/abstract.html

http://java.sun.com/docs/books/ tutorial / java / Concepts / interface.html

Короче говоря, абстрактный класс можно реализовать частично, а интерфейс - нет. Более подробная информация по ссылкам выше.

2
ответ дан 30 November 2019 в 12:00
поделиться

Как правильно объяснил KLE, основное различие между интерфейсом и абстрактным классом состоит в том, что абстрактный класс может содержать поля и тела методов, в то время как интерфейс может содержать только сигнатуры методов (и константы, т.е. общедоступные статические final fields).

Еще одно важное отличие состоит в том, что класс может реализовывать несколько интерфейсов, но он может наследовать только (напрямую) от одного класса (абстрактного или нет). Итак, для вещей, которые люди, вероятно, будут использовать в дополнение к другим функциям, интерфейс имеет больше смысла, чем абстрактный класс. См., Например, интерфейсы Comparable в JDK.

В качестве примера:

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

Итак, у нас есть абстрактный класс «Импорт», который содержит реализованные методы для таких вещей, как запись записей протокола, поиск всех файлов для импорта, удаление обработанных файлов импорта и т.д. import, поэтому существуют абстрактные методы, которые служат в качестве перехватчиков расширения, например getFilenamePattern (), который используется методом чтения для поиска файлов, которые можно импортировать. getFilenamePattern реализуется в конкретном подклассе, в зависимости от того, какие типы файлов необходимо импортировать.

Таким образом, общие функции импорта находятся в одном месте, а особенности для одного вида импорта являются отдельными.

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

Таким образом, общая функциональность импорта находится в одном месте, а особенности для одного вида импорта являются отдельными.

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

Таким образом, общая функциональность импорта находится в одном месте, а особенности для одного вида импорта являются отдельными.

3
ответ дан 30 November 2019 в 12:00
поделиться

If you need to wrap your head around the concept of abstract classes, take a look at the Swing UI toolkit (or at AWT) in the standard library.

Because you can imagine what can be visualized (e.g., a button, a label), it's easy to contrast it with the things that can't be instantiated (e.g., a JComponent).

2
ответ дан 30 November 2019 в 12:00
поделиться

Вы можете ограничить порядок выполнения инструкций определенными шагами, но разрешить делегирование поведения каждого шага:

public abstract class Instruction {

    void perform() {
        firstStep();
        secondStep();
        thirdStep();
    }

    abstract void firstStep();

    abstract void secondStep();

    abstract void thirdStep();

}
2
ответ дан 30 November 2019 в 12:00
поделиться

Интерфейс вообще не содержит реализации.

Абстрактный класс может содержать некоторую реализацию, которая полезна для всех подклассов, но не быть полной: ее нужно каким-то образом завершить в подклассах.
Если интерфейс позволяет использовать полиморфизм для нескольких классов, абстрактный класс также позволяет им повторно использовать код .

     public abstract class Figure {
        protected Point position;

        public abstract void draw();
     }

     public class Square extends Figure {
       // position is usable

       public void draw() {
         // this method must be implemented, for Square not to be abstract
       }

       // here is other code
     }

Еще одно отличие состоит в том, что класс может иметь только один суперкласс , но реализует множество интерфейсов. . Это может быть ограничивающим фактором.

2
ответ дан 30 November 2019 в 12:00
поделиться

Surprisingly, many examples/explanations given here do not provide good arguments for using an abstract class. Merely putting common fields/methods in a superclass does not require it to be abstract. Also (start rant), shame on supposedly knowledgeable engineers still coming up with Animal / Vehicle / Figure hierarchies to 'explain' object oriented concepts. These types of examples are very misleading because they point you in the wrong direction; you generally should NOT favour straight subclassing because it creates a very tight coupling between the classes. Rather use collaboration (rant ends).

So what do I think is a good use case for an abstract class? One of my favorite examples is an application of the 'template method' GoF pattern. Here you want to specify the generic flow of an algorithm once, but allow multiple implementations of the individual steps. Here an example I just put together of a VirusScanEngine containing the main virus scanning algorithm (find the next virus, either delete or report it, continue until scan is complete), and a LinearVirusScanner which implements the required algorithm steps (findVirus, deleteVirus and reportVirus). My apologies to all developers really working on virus scanning software for this horrendous simplification.

import java.util.Arrays;

public abstract class VirusScanEngine {

    public static void main(String[] args) {

        byte[] memory = new byte[] { 'a', 'b', 'c', 'M', 'e', 'l', 'i', 's', 's',
                'a' , 'd', 'e', 'f', 'g'};
        System.out.println("Before: " + Arrays.toString(memory));
        new LinearVirusScanner().scan(memory, Action.DELETE);
        System.out.println("After: " + Arrays.toString(memory));
    }

    public enum Action {
        DELETE, REPORT
    };

    public boolean scan(byte[] memory, Action action) {

        boolean virusFound = false;
        int index = 0;
        while (index < memory.length) {

            int size = findVirus(memory, index);
            if (size > 0) {
                switch (action) {

                case DELETE:
                    deleteVirus(memory, index, size);
                    break;
                case REPORT:
                    reportVirus(memory, index, size);
                    break;
                }
                index += size;
            }
            index++;
        }
        return virusFound;
    }

    abstract int findVirus(byte[] memory, int startIndex);

    abstract void reportVirus(byte[] memory, int startIndex, int size);

    abstract void deleteVirus(byte[] memory, int startIndex, int size);
}

and

public class LinearVirusScanner extends VirusScanEngine {

    private static final byte[][] virusSignatures = new byte[][] {
            new byte[] { 'I', 'L', 'O', 'V', 'E', 'Y', 'O', 'U' },
            new byte[] { 'M', 'e', 'l', 'i', 's', 's', 'a' } };

    @Override
    int findVirus(byte[] memory, int startIndex) {

        int size = 0;
        signatures: for (int v = 0; v < virusSignatures.length; v++) {

            scan: {
                for (int t = 0; t < virusSignatures[v].length; t++) {

                    if (memory[startIndex + t] != virusSignatures[v][t]) {
                        break scan;
                    }
                }
                // virus found
                size = virusSignatures[v].length;
                break signatures;
            }
        }
        return size;
    }

    @Override
    void deleteVirus(byte[] memory, int startIndex, int size) {

        for (int n = startIndex; n < startIndex + size - 1; n++) {
            memory[n] = 0;
        }
    }

    @Override
    void reportVirus(byte[] memory, int startIndex, int size) {

        System.out.println("Virus found at position " + startIndex
                + " with length " + size);
    }
}
4
ответ дан 30 November 2019 в 12:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: