В чем разница между интерфейсом и абстрактным классом? - PullRequest
1651 голосов
/ 16 декабря 2009

В чем именно разница между интерфейсом и абстрактным классом?

Ответы [ 34 ]

12 голосов
/ 23 июля 2014

Это довольно просто на самом деле.

Вы можете думать об интерфейсе как о классе, которому разрешено иметь только абстрактные методы и ничего больше.

Таким образом, интерфейс может только «объявлять» и не определять поведение, которое должен иметь класс.

Абстрактный класс позволяет вам как объявлять (используя абстрактные методы), так и определять (используя полную реализацию метода) поведение, которое должен иметь класс.

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

Последнее,

В Java вы можете реализовать несколько интерфейсов, но вы можете расширить только один (абстрактный класс или класс) ...

Это означает, что наследование определенного поведения ограничено, чтобы разрешить только одно на класс ... т.е. если вы хотите, чтобы класс, инкапсулирующий поведение из классов A, B и C, вам нужно было бы сделать следующее: класс A расширяет B, класс C расширяет А ... это немного о способе множественного наследования ...

Интерфейсы с другой стороны, вы могли бы просто сделать: интерфейс C реализует A, B

Таким образом, в действительности Java поддерживает множественное наследование только в «объявленном поведении», то есть в интерфейсах, и только одиночное наследование с определенным поведением ... если только вы не выполните описанный мной способ ...

Надеюсь, это имеет смысл.

11 голосов
/ 25 июля 2014

Неверное сравнение интерфейса с абстрактным классом. Вместо этого должно быть два других сравнения: 1) интерфейс против класса и 2) аннотация против финального класса .

Интерфейс против класса

Интерфейс - это контракт между двумя объектами. Например, я почтальон, а ты посылка для доставки. Я ожидаю, что вы знаете свой адрес доставки. Когда кто-то дает мне посылку, он должен знать ее адрес доставки:

interface Package {
  String address();
}

Класс - это группа объектов, которые подчиняются договору. Например, я ящик из группы "Ящик" и подчиняюсь договору, требуемому Почтальоном. В то же время я подчиняюсь другим контрактам:

class Box implements Package, Property {
  @Override
  String address() {
    return "5th Street, New York, NY";
  }
  @Override
  Human owner() {
    // this method is part of another contract
  }
}

Аннотация против финала

Абстрактный класс - группа незавершенных объектов. Их нельзя использовать, потому что они пропускают некоторые части. Например, я - абстрактное поле с поддержкой GPS - я знаю, как проверить свое положение на карте:

abstract class GpsBox implements Package {
  @Override
  public abstract String address();
  protected Coordinates whereAmI() {
    // connect to GPS and return my current position
  }
}

Этот класс, если он унаследован / расширен другим классом, может быть очень полезным. Но само по себе - это бесполезно, так как не может иметь объектов. Абстрактные классы могут быть элементами построения конечных классов.

Финальный класс - это группа законченных объектов, которые можно использовать, но нельзя изменить. Они точно знают, как работать и что делать. Например, я ящик, который всегда идет по адресу, указанному при его создании:

final class DirectBox implements Package {
  private final String to;
  public DirectBox(String addr) {
    this.to = addr;
  }
  @Override
  public String address() {
    return this.to;
  }
}

В большинстве языков, таких как Java или C ++, может иметь только класс , ни абстрактный, ни окончательный. Такой класс может быть унаследован и может быть создан. Я не думаю, что это строго соответствует объектно-ориентированной парадигме.

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

8 голосов
/ 25 августа 2014

Разница лишь в том, что один может участвовать в множественном наследовании, а другой нет.

Определение интерфейса со временем изменилось. Как вы думаете, интерфейс имеет только объявления методов и является просто контрактами? Как насчет статических конечных переменных и определений по умолчанию после Java 8?

Интерфейсы были введены в Java из-за проблемы с алмазом с множественным наследованием, и именно это они и намерены делать.

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

См. Почему Java допускает статические конечные переменные в интерфейсах, когда они предназначены только для контрактов? .

8 голосов
/ 27 июня 2017

Короче различия следующие:

Синтаксические различия между Интерфейсом и Абстрактный класс :

  1. Методы и члены абстрактного класса могут иметь любую видимость. Все методы интерфейса должны быть public . // Больше не выполняется в Java 9
  2. Конкретный дочерний класс Abstract Класс должен определять все абстрактные методы. Abstract дочерний класс может иметь абстрактные методы. Интерфейс , расширяющий другой интерфейс, не должен обеспечивать реализацию по умолчанию для методов, унаследованных от родительского интерфейса.
  3. Дочерний класс может расширять только один класс. Интерфейс может расширять несколько интерфейсов. Класс может реализовывать несколько интерфейсов.
  4. Дочерний класс может определять абстрактные методы с такой же или менее ограничительной видимостью, тогда как класс, реализующий интерфейс , должен определять все методы интерфейса как общедоступные.
  5. Абстрактные классы могут иметь конструкторы, но не интерфейсы .
  6. Интерфейсы из Java 9 имеют частные статические методы.

В интерфейсах сейчас:

public static - поддерживается
public abstract - поддерживается
public default - поддерживается
private static - поддерживается
private abstract - ошибка компиляции
private default - ошибка компиляции
private - поддерживается

7 голосов
/ 07 марта 2017

Интерфейс: повернуть (повернуть налево, повернуть направо).

Абстрактный класс: Колесо.

Класс: рулевое колесо, происходит от колеса, подвергается повороту интерфейса

Один предназначен для категоризации поведения, которое может быть предложено в широком диапазоне вещей, другой - для моделирования онтологии вещей.

6 голосов
/ 03 октября 2017

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

Следующие примеры демонстрируют это.

Абстрактный класс на Java:

abstract class animals
{
    // They all love to eat. So let's implement them for everybody
    void eat()
    {
        System.out.println("Eating...");
    }
    // The make different sounds. They will provide their own implementation.
    abstract void sound();
}

class dog extends animals
{
    void sound()
    {
        System.out.println("Woof Woof");
    }
}

class cat extends animals
{
    void sound()
    {
        System.out.println("Meoww");
    }
}

Ниже приведена реализация интерфейса в Java:

interface Shape
{
    void display();
    double area();
}

class Rectangle implements Shape 
{
    int length, width;
    Rectangle(int length, int width)
    {
        this.length = length;
        this.width = width;
    }
    @Override
    public void display() 
    {
        System.out.println("****\n* *\n* *\n****"); 
    }
    @Override
    public double area() 
    {
        return (double)(length*width);
    }
} 

class Circle implements Shape 
{
    double pi = 3.14;
    int radius;
    Circle(int radius)
    {
        this.radius = radius;
    }
    @Override
    public void display() 
    {
        System.out.println("O"); // :P
    }
    @Override
    public double area() 
    { 
        return (double)((pi*radius*radius)/2);
    }
}

Некоторые важные ключевые моменты в двух словах:

  1. Переменные, объявленные в интерфейсе Java, по умолчанию являются окончательными. Абстрактные классы могут иметь не конечные переменные.

  2. Переменные, объявленные в интерфейсе Java, по умолчанию являются статическими. Абстрактные классы могут иметь нестатические переменные.

  3. Члены интерфейса Java по умолчанию являются публичными. Абстрактный класс Java может иметь обычные разновидности членов класса, например private, protected и т. Д.

4 голосов
/ 16 декабря 2009

Не совсем ответ на первоначальный вопрос, но как только вы получите ответ на разницу между ними, вы введете дилемму «когда использовать»: Когда использовать интерфейсы или абстрактные классы? Когда использовать оба?

Я ограничил знание ООП, но рассмотрение интерфейсов как эквивалента прилагательного в грамматике до сих пор работало для меня (поправьте меня, если этот метод фальшивый!). Например, имена интерфейсов похожи на атрибуты или возможности, которые вы можете дать классу, и у класса может быть много из них: ISerializable, ICountable, IList, ICacheable, IHappy, ...

3 голосов
/ 28 июня 2017

Чтобы дать простой, но ясный ответ, это помогает установить контекст: вы используете оба, когда не хотите предоставлять полную реализацию.

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

3 голосов
/ 16 августа 2017

Различия между абстрактным классом и интерфейсом от имени реальной реализации.

Интерфейс : Это ключевое слово, которое используется для определения шаблона или чертежа объекта, и оно заставляет все подклассы следовать одному и тому же прототипу, как в случае реализации, все подклассы классы могут свободно реализовывать функциональность в соответствии с требованиями.

Некоторые другие случаи использования интерфейса.

Связь между двумя внешними объектами (сторонняя интеграция в нашем приложении) осуществляется через Интерфейс здесь Интерфейс работает как Контракт.

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

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

 public abstract class DesireCar
  {

 //It is an abstract method that defines the prototype.
     public abstract void Color();

  // It is a default implementation of a Wheel method as all the desire cars have the same no. of wheels.   
 // and hence no need to define this in all the sub classes in this way it saves the code duplicasy     

  public void Wheel() {          

               Console.WriteLine("Car has four wheel");
                }
           }


    **Here is the sub classes:**

     public class DesireCar1 : DesireCar
        {
            public override void Color()
            {
                Console.WriteLine("This is a red color Desire car");
            }
        }

        public class DesireCar2 : DesireCar
        {
            public override void Color()
            {
                Console.WriteLine("This is a red white Desire car");
            }
        }

Пример интерфейса:

  public interface IShape
        {
          // Defines the prototype(template) 
            void Draw();
        }


  // All the sub classes follow the same template but implementation can be different.

    public class Circle : IShape
    {
        public void Draw()
        {
            Console.WriteLine("This is a Circle");
        }
    }

    public class Rectangle : IShape
    {
        public void Draw()
        {
            Console.WriteLine("This is a Rectangle");
        }
    }
3 голосов
/ 20 ноября 2014

Ключевые моменты:

  • Абстрактный класс может иметь свойство, Поля данных, Методы (завершено / неполный) оба.
  • Если метод или Properties определяют абстрактное ключевое слово, которое должно переопределяться в производном классе. (Его работа тесно связана функциональность)
  • Если вы определяете абстрактное ключевое слово для метода или свойств в абстрактном классе, вы не можете определить тело метода и получить / установить значение для свойства и которые должны быть переопределены в производном классе.
  • Абстрактный класс не поддерживает множественное наследование.
  • Абстрактный класс содержит конструкторы.
  • Абстрактный класс может содержать модификаторы доступа для подпрограмм, функций, свойств.
  • Статическим может быть только полный член абстрактного класса.
  • Интерфейс может наследовать только от другого интерфейса и не может наследовать от абстрактного класса, тогда как абстрактный класс может наследовать от другого абстрактного класса или другого интерфейса.

Преимущество:

  • Это своего рода контракт, который заставляет все подклассы придерживаться одинаковых иерархий или стандартов.
  • Если различные реализации имеют одинаковый вид и используют общее поведение или статус, тогда лучше использовать абстрактный класс.
  • Если мы добавим новый метод в абстрактный класс, тогда у нас будет возможность обеспечить реализацию по умолчанию, и, следовательно, весь существующий код может работать должным образом.
  • Это позволяет выполнять быстрее, чем интерфейс. (Интерфейс Требуется больше времени, чтобы найти фактический метод в соответствующих классах.)
  • Может использоваться для плотного и слабого сцепления.

подробности здесь ... http://pradeepatkari.wordpress.com/2014/11/20/interface-and-abstract-class-in-c-oops/

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