состав в ООП, какой из них правильный? [Дубликат]

Немного странно, но приятно. Я использую String, а не BigDecimal

def round(x: Double)(p: Int): Double = {
    var A = x.toString().split('.')
    (A(0) + "." + A(1).substring(0, if (p > A(1).length()) A(1).length() else p)).toDouble
}
160
задан Péter Török 28 June 2010 в 16:38
поделиться

16 ответов

Они совершенно разные. Наследование - это отношение "is-a" . Композиция представляет собой «has-a» .

Вы выполняете композицию, имея экземпляр другого класса C в качестве поля вашего класса, вместо расширения C. Хорошим примером, где состав был бы намного лучше, чем наследование, является java.util.Stack, который в настоящее время распространяется java.util.Vector. Это сейчас считается ошибкой. Стек "- это-НЕ-a" вектор; вам не разрешается вставлять и удалять элементы произвольно. Это должно было быть композиция.

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

Я очень рекомендую книгу Джоша Блоха Эффективная Java 2-е издание

  • Пункт 16: Положительная композиция над наследованием
  • Пункт 17: Дизайн и документ для наследования или запрет на него

Хороший объектно-ориентированный дизайн - это не либеральное расширение существующих классов. Ваш первый инстинкт должен составлять вместо этого.


См. Также:

234
ответ дан polygenelubricants 19 August 2018 в 05:21
поделиться
  • 1
    это отличная помощь – Sikander 4 May 2013 в 21:49
  • 2
    Интересно. Почему бы просто не создать новый класс java.util.Stack2, который использует композицию? – qed 7 November 2014 в 14:37
  • 3
    Я ценю этот ответ; тем не менее, я чувствую, что ответ выходит из-под контроля и больше вникает в проблемы, связанные с дизайном языка (и конкретного пакета), чем он отвечает на заданный вопрос о композиции против наследования. Я большой поклонник ответа на вопрос о SO, ссылаясь на ресурсы - не ссылаясь на внешние ресурсы, не предоставляя более подробное резюме, чем однострочное суммирование. – Thomas 23 January 2015 в 15:09
  • 4
    танк ты отличный ответ – Hosseini 16 May 2016 в 07:24
  • 5
    Плохой пример, я должен был сделать дополнительный поиск, чтобы понять, что такое Vector и Stack. – Sam Ramezanli 25 March 2017 в 17:30

Элементы композиции HAS A Наследование означает IS A

Example: автомобиль имеет двигатель и автомобиль - это автомобиль

. При программировании это выглядит как:

class Engine {} // The Engine class.

class Automobile {} // Automobile class which is parent to Car class.

class Car extends Automobile { // Car is an Automobile, so Car class extends Automobile class.
  private Engine engine; // Car has an Engine so, Car class has an instance of Engine class as its member.
}
149
ответ дан Andrea Bergonzo 19 August 2018 в 05:21
поделиться
  • 1
    Я бы изменил «автомобиль». к "приведенному в действие транспортному средству" как и во многих интертратациях, автомобили и автомобили эквивалентны. – Andrey Akhmetov 25 November 2013 в 00:02
  • 2
    @hexafraction Я согласен с тем, что автомобиль, скорее всего, будет лучшим выбором, но в то же время -codaddict-проиллюстрировал точку просто отлично для того, что было задано. – nckbrz 27 March 2014 в 19:46
  • 3
    Этот пример действительно полезен. – user2180794 9 May 2016 в 02:05
  • 4
    "Двигатель" :-/ – Omar Tariq 14 December 2016 в 11:32
  • 5
    Это лучший ответ! – Melchia 1 February 2018 в 09:53

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

4
ответ дан BlackICE 19 August 2018 в 05:21
поделиться

Являются ли композиция и наследование одинаковыми?

Они не совпадают.

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

Inheritance : класс наследует поля и методы из все его суперклассы, прямые или косвенные. Подкласс может переопределять методы, которые он наследует, или он может скрыть поля или методы, которые он наследует.

Если я хочу реализовать шаблон композиции, как я могу это сделать на Java?

Статья в Википедии достаточно хороша для реализации составного шаблона в java.

Ключевые участники:

Компонент:

  1. Является абстракцией для всех компонентов, включая составные
  2. Объявляет интерфейс для объектов в композиция

Лист:

  1. Представляет листовые объекты в композиции
  2. Реализует все методы Component

Композит:

  1. Представляет составной компонент (компонент с дочерними элементами)
  2. Реализует методы манипулирования детьми
  3. Реализует все методы Component, обычно делегируя их своим детям

Пример кода для понимания Composite patter n:

import java.util.List;
import java.util.ArrayList;

interface Part{
    public double getPrice();
    public String getName();
}
class Engine implements Part{
    String name;
    double price;
    public Engine(String name,double price){
        this.name = name;
        this.price = price;
    }
    public double getPrice(){
        return price;
    }
    public String getName(){
        return name;
    }
}
class Trunk implements Part{
    String name;
    double price;
    public Trunk(String name,double price){
        this.name = name;
        this.price = price;
    }
    public double getPrice(){
        return price;
    }
    public String getName(){
        return name;
    }
}
class Body implements Part{
    String name;
    double price;
    public Body(String name,double price){
        this.name = name;
        this.price = price;
    }
    public double getPrice(){
        return price;
    }
    public String getName(){
        return name;
    }
}
class Car implements Part{
    List<Part> parts;
    String name;

    public Car(String name){
        this.name = name;
        parts = new ArrayList<Part>();
    }
    public void addPart(Part part){
        parts.add(part);
    }
    public String getName(){
        return name;
    }
    public String getPartNames(){
        StringBuilder sb = new StringBuilder();
        for ( Part part: parts){
            sb.append(part.getName()).append(" ");
        }
        return sb.toString();
    }
    public double getPrice(){
        double price = 0;
        for ( Part part: parts){
            price += part.getPrice();
        }
        return price;
    }   
}

public class CompositeDemo{
    public static void main(String args[]){
        Part engine = new Engine("DiselEngine",15000);
        Part trunk = new Trunk("Trunk",10000);
        Part body = new Body("Body",12000);

        Car car = new Car("Innova");
        car.addPart(engine);
        car.addPart(trunk);
        car.addPart(body);

        double price = car.getPrice();

        System.out.println("Car name:"+car.getName());
        System.out.println("Car parts:"+car.getPartNames());
        System.out.println("Car price:"+car.getPrice());
    }

}

выход:

Car name:Innova
Car parts:DiselEngine Trunk Body
Car price:37000.0

Объяснение:

  1. Часть - это лист
  2. Автомобиль содержит много частей
  3. В автомобиль добавлены запчасти автомобиля
  4. Цена Автомобиль = сумма (Цена каждой партии)

См. ниже вопрос о преимуществах и недостатках композиции и наследования.

Предпочитают композицию по наследованию?

4
ответ дан Community 19 August 2018 в 05:21
поделиться
  • 1
    Имеет ли смысл внедрять детали для класса автомобилей. Не будет ли это хорошо, если вы будете использовать его в качестве композиции – bhalkian 20 March 2018 в 05:09

Композиция точно так же звучит - вы создаете объект, вставляя части.

ИЗМЕНИТЬ, что остальная часть этого ответа ошибочно основана на следующем посылке. Это достигается с помощью интерфейсов. Например, используя вышеприведенный пример Car,

Car implements iDrivable, iUsesFuel, iProtectsOccupants
Motorbike implements iDrivable, iUsesFuel, iShortcutThroughTraffic
House implements iProtectsOccupants
Generator implements iUsesFuel

Итак, с помощью нескольких стандартных теоретических компонентов вы можете создать свой объект. Это ваша работа, чтобы заполнить, как House защищает своих обитателей и как Car защищает своих обитателей.

Наследование походит на все наоборот. Вы начинаете с полного (или полуполного) объекта, и вы заменяете или переопределяете различные биты, которые хотите изменить.

Например, MotorVehicle может поставляться с методом Fuelable и Drive метод. Вы можете оставить метод Fuel так, как он есть, потому что это то же самое, что и заполнять мотоцикл и автомобиль, но вы можете переопределить метод Drive, потому что Motorbike очень сильно отличается от Car.

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

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

iFuelable Interface:
   void AddSomeFuel()
   void UseSomeFuel()
   int  percentageFull()

, тогда у вас может быть метод где-то еще

private void FillHerUp(iFuelable : objectToFill) {

   Do while (objectToFill.percentageFull() <= 100)  {

        objectToFill.AddSomeFuel();
   }

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

Если вы использовали Inheritance вместо этого, вам понадобятся разные методы FillHerUp для работы с MotorVehicles и Barbecues, если у вас не было какого-то довольно странного базового объекта ObjectThatUsesFuel, из которого унаследовать.

7
ответ дан dlamblin 19 August 2018 в 05:21
поделиться
  • 1
    В соглашениях Java указано, что имена классов и интерфейсов записаны в ThisCase, а не в camelCase. Поэтому лучше всего назвать ваши интерфейсы IDrivable и т. Д. Возможно, вам не понадобится «I». если вы правильно перегруппируете все свои интерфейсы в пакет. – ThePyroEagle 21 December 2015 в 11:15

Наследование выявляет отношение IS-A. Композиция выявляет связь HAS-A. Шаблон Statergy объясняет, что композиция должна использоваться в тех случаях, когда существуют семейства алгоритмов, определяющих конкретное поведение. Классический пример - тип утки, который реализует поведение мух.

public interface Flyable{
     public void fly();
}

public class Duck {
Flyable fly;

 public Duck(){
  fly=new BackwardFlying();
 }

}

Таким образом, мы можем иметь несколько классов которые реализуют полет, например:

public class BackwardFlying implements Flyable{
  public void fly(){
     Systemout.println("Flies backward ");
 }
}
 public class FastFlying implements Flyable{
  public void fly(){
     Systemout.println("Flies 100 miles/sec");
 }
}

Если бы для наследования у нас было бы два разных класса птиц, которые снова и снова реализуют функцию мух. Это наследование и состав совершенно разные.

14
ответ дан frictionlesspulley 19 August 2018 в 05:21
поделиться

Композиция означает создание объекта для класса, который имеет отношение к этому конкретному классу. Предположим, что у Студента есть связь с Учётами;

Наследование - это предыдущий класс с расширенной функцией. Это означает, что этот новый класс - это класс Old с некоторой расширенной функцией. Предположим, что студент - студент, но все ученики - это люди. Так что есть отношения со студентами и людьми. Это Наследование.

0
ответ дан HM Nayem 19 August 2018 в 05:21
поделиться

В «Агрегации простого слова» означает «Отношения».

Состав - это особый случай агрегации. Более конкретно, ограниченная агрегация называется композицией. Когда объект содержит другой объект, если содержащийся объект не может существовать без существования контейнерного объекта, тогда он называется композицией. Пример: класс содержит студентов. Студент не может существовать без класса. Существует композиция между классом и учениками.

Зачем использовать Aggregation

Повторное использование кода

Когда использование агрегирования

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

Наследование

Наследование является родительским отношением к дочерним отношениям, связанным с отношением. RelationShip

Наследование в Java - это механизм, в котором один объект приобретает все свойства и поведение родительского объекта.

Использование наследования в Java 1 Повторное использование кода. 2 Добавить дополнительную функцию в дочернем классе, а также переопределение метода (поэтому может быть достигнут полиморфизм выполнения).

3
ответ дан Keshav Gera 19 August 2018 в 05:21
поделиться

Хотя оба наследования и композиции обеспечивают повторное использование кода, основное различие между композицией и наследованием в Java заключается в том, что Composition позволяет повторно использовать код без его расширения, но для Inheritance вы должны расширить класс для повторного использования кода или функциональности. Другое отличие от этого факта заключается в том, что с помощью композиции вы можете повторно использовать код для даже окончательного класса, который не является расширяемым, но Inheritance не может повторно использовать код в таких случаях. Кроме того, используя Composition, вы можете повторно использовать код из многих классов, поскольку они объявлены как только переменная-член, но с Inheritance вы можете повторно использовать форму кода только одного класса, потому что в Java вы можете расширять только один класс, поскольку множественное Наследование не поддерживается в Java , Вы можете сделать это на C ++, хотя из-за того, что один класс может расширять несколько классов. Кстати, вы всегда должны предпочитать композицию над наследованием в Java, ее не только я, но даже Джошуа Блох предложил в своей книге

2
ответ дан Nitin Pawar 19 August 2018 в 05:21
поделиться

Как наследование может быть опасным?

Давайте возьмем пример

public class X{    
   public void do(){    
   }    
}    
Public Class Y extends X{
   public void work(){    
       do();    
   }
}

1) Как ясно в приведенном выше коде, класс Y имеет очень сильную связь с классом X. Если что-либо изменения в суперклассе X, Y могут резко нарушиться. Предположим, что в будущем класс X реализует работу метода с подписи

public int work(){
}

. Изменение выполняется в классе X, но это сделает класс Y несовместимым. Так что такая зависимость может подниматься до любого уровня, и это может быть опасно. Каждый раз, когда суперкласс может не иметь полной видимости для кода внутри всех его подклассов, и подкласс может постоянно замечать, что происходит в suerclass все время. Поэтому мы должны избегать этой сильной и ненужной связи.

Как композиция решает эту проблему?

Давайте посмотрим, пересматривая тот же пример

public class X{
    public void do(){
    }
}

Public Class Y{
    X x=new X();    
    public void work(){    
        x.do();
    }
}

Здесь мы создаем ссылку на класс X в классе Y и вызываем метод класса X, создавая экземпляр класса X. Теперь вся эта сильная связь исчезла. Суперклассы и подклассы теперь очень независимы друг от друга. Классы могут свободно вносить изменения, которые были опасны в ситуации наследования.

2) Второе очень хорошее преимущество композиции в том, что оно обеспечивает гибкость вызова метода. Например,

class X implements R
{}
class Y implements R
{}

public class Test{    
    R r;    
}

В классе Test с использованием r reference Я могу вызывать методы класса X, а также класс Y. Эта гибкость никогда не существовала в наследовании

3) Еще одно большое преимущество: Unit testing

public class X{
    public void do(){
    }
}

Public Class Y{
    X x=new X();    
    public void work(){    
        x.do();    
    }    
}

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

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

Давайте рассмотрим пример:

Public class Transaction {
    Banking b;
    public static void main(String a[])    
    {    
        b=new Deposit();    
        if(b.deposit()){    
            b=new Credit();
            c.credit();    
        }
    }
}

Полезно знать:

  1. состав легко достигается во время выполнения, в то время как наследование обеспечивает его функции во время компиляции
  2. также известны как отношение HAS-A, а наследование также известно как отношение IS-A

. Поэтому сделайте его привычкой всегда предпочитать состав над наследованием по разным причинам.

17
ответ дан Radim Köhler 19 August 2018 в 05:21
поделиться

Нет, оба они разные. Композиция соответствует отношениям «HAS-A» и наследованию следуют отношения «IS-A». Лучшим примером для композиции был стратегический паттерн.

0
ответ дан Ranga Reddy 19 August 2018 в 05:21
поделиться
  • 1
    Его единственное качество комментариев – Billa 24 December 2017 в 18:51
  • 2
    Вы просто прокомментировали то же самое, что принятый ответ сказал за 7 лет до вас? – Anjil Dhamala 9 February 2018 в 15:52

Я думаю, что этот пример ясно объясняет различия между наследованием и композицией.

В этом случае проблема решена с использованием наследования и композиции. Автор обращает внимание на то, что; в наследовании изменение в суперклассе может вызвать проблемы в производном классе, которые наследуют его.

Там вы также можете увидеть разницу в представлении, когда используете UML для наследования или композиции.

http://www.javaworld.com/article/2076814/core-java/inheritance-versus-composition--which-one-should-you-choose-.html

16
ответ дан Ravindra babu 19 August 2018 в 05:21
поделиться
  • 1
    большой ответ и разъяснение. – StackOverflowed 15 September 2012 в 23:38
  • 2
    Ссылка только ответы обескуражены, потому что они устаревают. Пожалуйста, укажите, по крайней мере, самую важную релевантную информацию из ссылки в вашем ответе. – Okuma.Scott 18 March 2014 в 14:17

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

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

Я не знаю Java, поэтому я не могу представить пример, но я могу дать объяснение понятий.

2
ответ дан Robert Rocha 19 August 2018 в 05:21
поделиться

Наследование Vs Состав.

Наследования и состав используются для повторного использования и расширения поведения класса.

Наследование в основном используется в модели программирования алгоритмов семейства, такой как тип отношения IS-A, означает аналогичный объект. Пример.

  1. Duster - автомобиль
  2. Safari - это автомобиль

. Они принадлежат семейству Car.

Композиция представляет собой отношение HAS-A Type.It показывает способность объекта, такого как Duster, иметь Five Gears, Safari имеет четыре Gears и т. д. Всякий раз, когда нам нужно расширить способность существующего класса, используйте композицию. Например, нам нужно добавить еще одна передача в объекте Duster, тогда мы должны создать еще один объект передачи и скомпоновать его объекту duster.

Мы не должны вносить изменения в базовый класс до тех пор, пока все производные классы не нуждаются в этих функциях. Для этого сценария мы должны использовать Composition.Such как

класс A Производится классом B

Класс A Производится классом C

Класс A Производится классом D.

Когда мы добавляем какие-либо функциональные возможности в класс А, тогда он доступен для всех подклассов, даже если классам C и D не требуются эти функции. Для этого сценария нам необходимо создать отдельный класс для этих функций и составить это к требуемому классу (вот класс B).

Ниже приведен пример:

          // This is a base class
                 public abstract class Car
                    {
                       //Define prototype
                       public abstract void color();
                       public void Gear() {
                           Console.WriteLine("Car has a four Gear");
                       }
                    }


           // Here is the use of inheritence
           // This Desire class have four gears.
          //  But we need to add one more gear that is Neutral gear.

          public class Desire : Car
                   {
                       Neutral obj = null;
                       public Desire()
                       {
     // Here we are incorporating neutral gear(It is the use of composition). 
     // Now this class would have five gear. 

                           obj = new Neutral();
                           obj.NeutralGear();
                       }

                       public override void color()
                       {
                           Console.WriteLine("This is a white color car");
                       }

                   }


             // This Safari class have four gears and it is not required the neutral
             //  gear and hence we don't need to compose here.

                   public class Safari :Car{
                       public Safari()
                       { }

                       public override void color()
                       {
                           Console.WriteLine("This is a red color car");
                       }


                   }

   // This class represents the neutral gear and it would be used as a composition.

   public class Neutral {
                      public void NeutralGear() {
                           Console.WriteLine("This is a Neutral Gear");
                       }
                   }
1
ответ дан Sheo Dayal Singh 19 August 2018 в 05:21
поделиться

Inheritence означает повторное использование полной функциональности класса. Здесь мой класс должен использовать все методы суперкласса, и мой класс будет связан с суперклассом, и код будет дублироваться в обоих классах в случае наследования .

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

0
ответ дан Vikas Kapadiya 19 August 2018 в 05:21
поделиться
16
ответ дан Ravindra babu 30 October 2018 в 17:18
поделиться
Другие вопросы по тегам:

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