IT story

Java 또는 C #에서 다중 상속이 허용되지 않는 이유는 무엇입니까?

hot-time 2020. 8. 4. 22:51
반응형

Java 또는 C #에서 다중 상속이 허용되지 않는 이유는 무엇입니까?


Java 및 C #에서는 다중 상속이 허용되지 않습니다. 많은 책들은 단지 다중 상속이 허용되지 않는다고 말합니다. 그러나 인터페이스를 사용하여 구현할 수 있습니다. 허용되지 않는 이유에 대해서는 논의되지 않았습니다. 아무도 왜 그것이 허용되지 않는지 정확하게 말해 줄 수 있습니까?


짧은 답은 언어 디자이너들이하지 않기로 결정했기 때문입니다.

기본적으로 .NET 및 Java 디자이너는 MI를 추가 하면 언어 에 너무 많은 복잡성추가 되고 이점이 거의 없기 때문에 다중 상속을 허용하지 않는 것 같습니다 .

보다 재미 있고 심도있는 읽기를 위해 일부 언어 디자이너와의 인터뷰를 통해 웹에 제공되는 기사가 있습니다. 예를 들어 .NET의 경우 CLR에서 MS에서 근무한 Chris Brumme은 다음과 같이하지 않기로 결정한 이유를 설명했습니다.

  1. 실제로 언어마다 MI의 작동 방식에 대한 기대치가 다릅니다. 예를 들어 충돌이 해결되는 방법과 중복 기준의 병합 또는 중복 여부입니다. CLR에서 MI를 구현하기 전에 모든 언어를 조사하고 일반적인 개념을 파악한 후 언어 중립적 인 방식으로 표현하는 방법을 결정해야합니다. 또한 MI가 CLS에 속하는지 여부와이 개념을 원하지 않는 언어 (예 : VB.NET)에 대한 의미를 결정해야합니다. 물론, 이것이 우리가 공용 언어 런타임으로하는 ​​사업이지만, 아직 MI를 위해 그 일을하지 않았습니다.

  2. MI가 정말로 적합한 장소의 수는 실제로 상당히 적습니다. 대부분의 경우 여러 인터페이스 상속이 대신 작업을 수행 할 수 있습니다. 다른 경우에는 캡슐화 및 위임을 사용할 수 있습니다. 믹스 인과 같이 약간 다른 구성을 추가한다면 실제로 더 강력할까요?

  3. 다중 구현 상속은 구현에 많은 복잡성을 주입합니다. 이 복잡성은 캐스팅, 레이아웃, 디스패치, 필드 액세스, 직렬화, ID 비교, 검증 가능성, 반영, 제네릭 및 기타 여러 장소에 영향을줍니다.

여기에서 전체 기사를 읽을 수 있습니다.

Java의 경우이 기사를 읽을 수 있습니다 .

Java 언어에서 다중 상속을 생략하는 이유는 주로 "단순하고 객체 지향적이며 친숙한"목표에서 비롯됩니다. Java 제작자는 간단한 언어로서 대부분의 개발자가 광범위한 교육을받지 않고도 이해할 수있는 언어를 원했습니다. 이를 위해, 그들은 C ++의 불필요한 복잡성 (간단한)을 넘지 않고 가능한 한 C ++과 유사한 언어를 만들기 위해 노력했습니다.

디자이너의 의견으로는 다중 상속은 해결하는 것보다 더 많은 문제와 혼란을 야기합니다. 따라서 연산자 오버로드를 줄이는 것처럼 언어에서 여러 상속을 자릅니다. 디자이너의 광범위한 C ++ 경험은 다중 상속은 그만한 가치가 없다고 가르쳤다.


구현의 다중 상속은 허용되지 않습니다.

문제는 컴파일러 / 런타임이 draw () 메소드에 대한 구현과 함께 Cowboy 및 Artist 클래스를 가지고있는 경우 수행 할 작업을 파악할 수없고 새 CowboyArtist 유형을 작성하려고한다는 것입니다. draw () 메서드를 호출하면 어떻게됩니까? 누군가가 길거리에서 죽었습니까? 아니면 아름다운 수채화가 있습니까?

나는 그것이 이중 다이아몬드 상속 문제라고 믿습니다.


이유 : Java는 단순성으로 인해 매우 인기 있고 코딩하기 쉽습니다.

따라서 자바 개발자가 프로그래머에게 이해하기 어렵고 복잡하다고 느끼는 것을 피하려고 노력했습니다. 그러한 종류의 재산 중 하나는 다중 상속입니다.

  1. 그들은 포인터를 피했다
  2. 그들은 다중 상속을 피했다.

다중 상속 문제 : 다이아몬드 문제.

:

  1. 클래스 A에 fun () 메소드가 있다고 가정하십시오. 클래스 B와 클래스 C는 클래스 A에서 파생됩니다.
  2. 그리고 클래스 B와 C는 모두 fun () 메소드를 대체합니다.
  3. 이제 클래스 D가 클래스 B와 C를 모두 상속한다고 가정합니다 (단지 가정).
  4. 클래스 D에 대한 객체를 만듭니다.
  5. D d = 새로운 D ();
  6. d.fun ()에 액세스하십시오. => 클래스 B의 fun () 또는 클래스 C의 fun ()을 호출합니까?

이것은 다이아몬드 문제에 존재하는 모호성입니다.

이 문제를 해결하는 것은 불가능하지 않지만, 읽는 동안 프로그래머에게 더 많은 혼란과 복잡성을 야기합니다. 해결하려고 시도하는 것보다 더 많은 문제가 발생합니다.

참고 : 그러나 인터페이스를 사용하여 항상 여러 상속을 간접적으로 구현할 수 있습니다.


Java는 C ++과 디자인 철학이 크게 다르기 때문입니다. (여기서 C #에 대해서는 논의하지 않겠습니다.)

C ++을 설계 할 때 Stroustrup은 오용 방법에 관계없이 유용한 기능을 포함하려고했습니다. 다중 상속, 연산자 오버로드, 템플릿 및 기타 다양한 기능을 사용하여 큰 시간을 허비 할 수는 있지만 매우 유용한 작업을 수행 할 수도 있습니다.

Java 디자인 철학은 언어 구성에서 안전을 강조하는 것입니다. 그 결과 훨씬 더 어색한 것들이 있지만,보고있는 코드가 생각하는 것을 의미한다고 훨씬 더 확신 할 수 있습니다.

또한 Java는 대부분 가장 잘 알려진 OO 언어 인 C ++과 Smalltalk의 반응이었습니다. MI를보다 잘 처리하는 다른 OO 시스템과 함께 다른 OO 언어 (공통 Lisp가 실제로 표준화 된 첫 번째 언어)가 많이 있습니다.

인터페이스, 컴포지션 및 위임을 사용하여 Java에서 MI를 수행하는 것은 전적으로 가능합니다. C ++보다 명시 적이므로 사용하기가 쉽지만 언뜻 이해하기 쉬운 것을 얻을 수 있습니다.

여기에는 정답이 없습니다. 다른 답변이 있으며 주어진 상황에 더 적합한 답변은 응용 프로그램 및 개인 취향에 따라 다릅니다.


사람들이 MI로부터 멀어지게하는 주된 이유는 (단, 반드시 유일한 것은 아님) 소위 "다이아몬드 문제"로 인해 구현에 애매함이 생길 수 있습니다. 위키 백과 기사 는 이에 대해 논의하고 내가 할 수있는 것보다 더 잘 설명합니다. MI는 또한 더 복잡한 코드로 이어질 수 있으며 많은 OO 디자이너는 MI가 필요 없다고 주장하며,이를 사용하면 모델이 잘못되었을 수 있습니다. 이 마지막 요점에 동의하지는 않지만 간단하게 유지하는 것이 항상 좋은 계획입니다.


C ++에서 다중 상속은 부적절하게 사용될 때 큰 두통이었습니다. 이러한 대중적인 디자인 문제를 피하기 위해 여러 인터페이스 "상속"이 현대 언어 (java, C #)로 대신 강요되었습니다.


다중 상속

  • 이해하기 어렵다
  • 디버깅하기 어렵습니다 (예를 들어, 동일한 이름의 메소드를 가진 여러 프레임 워크에서 클래스를 혼합하면 예상치 못한 시너지가 발생할 수 있습니다)
  • 잘못 사용하기 쉬운
  • 정말로 유용
  • 특히 정확 하고 효율적으로 수행하려는 경우 구현하기가 어렵습니다.

따라서 다중 상속을 Java 언어에 포함 시키지 않는 것이 현명한 선택으로 간주 될 수 있습니다 .


또 다른 이유는 단일 상속으로 캐스팅을 사소하게 만들고 어셈블러 명령을 생성하지 않습니다 (필요한 경우 유형의 호환성 확인 이외). 다중 상속이있는 경우 하위 클래스에서 특정 부모가 시작되는 위치를 파악해야합니다. 따라서 성능은 확실히 특권입니다 (단, 유일한 것은 아닙니다).


Back in the old days ('70s) when Computer Science was more Science and less mass production the programmers had time to think about good design and good implementation and as a result the products (programms) had high quality ( eg. TCP/IP design and implementation ). Nowadays, when everybody is programming, and the managers are changing the specs before deadlines, subtle issues like the one descriped in the wikipedia link from Steve Haigh post are difficult to track; therefore, the "multiple inheritance" is limited by compiler design. If you like it, you can still use C++ .... and have all the freedom you want :)


I take the statement that "Multiple inheritance is not allowed in Java" with a pinch of salt.

Multiple Inheritance is defined when a "Type" inherits from more than one "Types". And interfaces are also classified as types as they have behavior. So Java does have multiple inheritance. Just that it is safer.


Dynamic loading of classes makes the implementation of multiple inheritance difficult.

In java actually they avoided the complexity of multiple inheritance instead by using single inheritance and interface. Complexity of multiple inheritance is very high in a situation like below explained

diamond problem of multiple inheritance. We have two classes B and C inheriting from A. Assume that B and C are overriding an inherited method and they provide their own implementation. Now D inherits from both B and C doing multiple inheritance. D should inherit that overridden method, jvm can't able to decide which overridden method will be used?

In c++ virtual functions are used to handle and we have to do explicitly.

This can be avoided by using interfaces, there are no method bodies. Interfaces cannot be instantiated—they can only be implemented by classes or extended by other interfaces.


Actually multiple inheritance will arise a the complexity if the inherited classes have same function. ie the compiler will have a confusion which one has to chose (diamond problem). So in Java that complexity removed and gave interface to get the functionality like multiple inheritance gave. We can use interface


Java has concept, i.e. polymorphism. There are 2 types of polymorphism in java. There are method overloading and method overriding. Among them, method overriding happens with super- and subclass relationship. If we are creating an object of a subclass and invoking the method of superclass, and if subclass extends more than one class, which super class method should be called?

Or , while calling superclass constructor by super(), which super class constructor will get called?

This decisions are impossible by current java API features. so multiple inheritance is not allowed in java.


Multiple Inheritance is not allowed in Java directly , but through interfaces it is allowed.

Reason :

Multiple Inheritance : Introduces more complexity and ambiguity.

Interfaces : Interfaces are completely abstract classes in Java that provide you with a uniform way to properly delineate the structure or inner workings of your program from its publicly available interface, with the consequence being a greater amount of flexibility and reusable code as well as more control over how you create and interact with other classes.

More precisely, they are a special construct in Java with the additional characteristic that allow you to perform a kind of multiple inheritance i.e. classes that can be upcast to more than one class.

Lets take simple example.

  1. Suppose there are 2 superclasses classes A and B with same method names but different functionalities. Through following code with (extends) keyword multiple inheritance is not possible.

       public class A                               
         {
           void display()
             {
               System.out.println("Hello 'A' ");
             }
         }
    
       public class B                               
          {
            void display()
              {
                System.out.println("Hello 'B' ");
              }
          }
    
      public class C extends A, B    // which is not possible in java
        {
          public static void main(String args[])
            {
              C object = new C();
              object.display();  // Here there is confusion,which display() to call, method from A class or B class
            }
        }
    
  2. But through interfaces, with (implements) keyword multiple inheritance is possible.

    interface A
        {
           // display()
        }
    
    
     interface B
        {
          //display()
        }
    
     class C implements A,B
        {
           //main()
           C object = new C();
           (A)object.display();     // call A's display
    
           (B)object.display(); //call B's display
        }
    }
    

Can anybody tell me precisely why it is not allowed?

You can find answer from this documentation link

One reason why the Java programming language does not permit you to extend more than one class is to avoid the issues of multiple inheritance of state, which is the ability to inherit fields from multiple classes

If multiple inheritance is allowed and when you create an object by instantiating that class, that object will inherit fields from all of the class's super classes. It will cause two issues.

  1. What if methods or constructors from different super classes instantiate the same field?

  2. Which method or constructor will take precedence?

Even though multiple inheritance of state is now allowed, still you can implement

Multiple inheritance of type: Ability of a class to implement more than one interface.

Multiple inheritance of implementation (through default methods in interfaces) : Ability to inherit method definitions from multiple classes

Refer to this related SE question for additional info:

Multiple Inheritance Ambiguity with Interface


In C++ a class can inherit (directly or indirectly) from more than one class, which is referred to as multiple inheritance.

C# and Java, however, limit classes to single inheritance each class inherits from a single parent class.

Multiple inheritance is a useful way to create classes that combine aspects of two disparate class hierarchies, something that often happens when using different class frameworks within a single application.

If two frameworks define their own base classes for exceptions, for example, you can use multiple inheritance to create exception classes that can be used with either framework.

The problem with multiple inheritance is that it can lead to ambiguity. The classic example is when a class inherits from two other classes, each of which inherits from the same class:

class A {
    protected:
    bool flag;
};
class B : public A {};
class C : public A {};
class D : public B, public C {
    public:
    void setFlag( bool nflag ){
        flag = nflag; // ambiguous
    }
};

In this example, the flag data member is defined by class A. But class D descends from class B and class C, which both derive from A, so in essence two copies of flag are available because two instances of A are in D’s class hierarchy. Which one do you want to set? The compiler will complain that the reference to flag in D is ambiguous. One fix is to explicitly disambiguate the reference:

B::flag = nflag;

Another fix is to declare B and C as virtual base classes, which means that only one copy of A can exist in the hierarchy, eliminating any ambiguity.

Other complexities exist with multiple inheritance, such as the order in which the base classes are initialized when a derived object is constructed, or the way members can be inadvertently hidden from derived classes. To avoid these complexities, some languages restrict themselves to the simpler single inheritance model.

Although this does simplify inheritance considerably, it also limits its usefulness because only classes with a common ancestor can share behaviors. Interfaces mitigate this restriction somewhat by allowing classes in different hierarchies to expose common interfaces even if they’re not implemented by sharing code.


Imagine this Example: I have a class Shape1

It has CalcualteArea method:

Class Shape1
{

 public void CalculateArea()

     {
       //
     }
}

There is another class Shape2 that one also has same method

Class Shape2
{

 public void CalculateArea()

     {

     }
}

Now I have a child class Circle, it derives from both Shape1 and Shape2;

public class Circle: Shape1, Shape2
{
}

Now when I create object for Circle, and call the method, system does not know which calculate area method to be called. Both has same signatures. So compiler will get confuse. That's why multiple inheritances are not allowed.

But there can be multiple interfaces because interfaces do not have method definition. Even both the interfaces have same method, both of them do not have any implementation and always method in the child class will be executed.

참고URL : https://stackoverflow.com/questions/995255/why-is-multiple-inheritance-not-allowed-in-java-or-c

반응형