Множественное наследование - PullRequest
2 голосов
/ 12 августа 2010

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

Единственная причина этого вопроса в том, что я все больше и больше осознаюдля того, чтобы быть более трудоспособным, я должен знать либо Java и / или C #.

Хорошо, вот вопрос:

Я знаю, что множественное наследование запрещено в J и C #.Но если я сделаю что-то подобное (потому что я хотел бы иметь класс, который наследуется от двух классов B и A):

//code in Java
public class B
{
    public void methodFromB()
    {
    }
}

public class A extends B
{
    public void  methodFromA()
    {
    }
}

public class C extends A
{
    public void methodFromC()
    {
    }
}

Так что, насколько я понимаю, я наследую от обоихиз них (A и B, и да, я понимаю, что формальное объяснение этого заключается в том, что объект A является специализированным B, но, тем не менее, если я захочу это сделать, я сделаю это, но он просто выглядит не очень красиво)

Но вместо того, чтобы делать это в одном объявлении, я должен сначала создать один класс, унаследованный от другого, а затем наследовать от него?

Хотя это забавно.Объявив эти классы, как указано выше (в NetBeans), я вижу, что после создания экземпляра класса C (в основном) я не могу вызвать для него methodFromC, который является методом, определенным в этом классе.

В чем причинатот?

Спасибо.

Ответы [ 5 ]

7 голосов
/ 12 августа 2010

Даже если вы создаете экземпляр C, видимость методов Си зависит от используемого вами типа времени компиляции.Например,

C c = new C();
c.methodFromC();  // fine

Допустимо, но

A a = new C();
a.methodFromC();  // compiler error

- нет, поскольку тип времени компиляции - A, для которого не объявлено methodFromC.

Обратите внимание, что, поскольку C и A являются подклассами B, вызов methodFromB будет в порядке в обоих случаях.

6 голосов
/ 12 августа 2010

Я согласен с MDMA. Также обратите внимание, что это НЕ множественное наследование, это цепочечное наследование. Множественное наследование - это когда класс наследует от нескольких классов одновременно :

class A {}
class B {}

class C extends A, B {}

Что запрещено, если вы не программируете на C ++

2 голосов
/ 12 августа 2010

Это не множественное наследование. И вы правы, C # не поддерживает истинное множественное наследование. Для чего стоит канонический шаблон для имитации множественного наследования в C # ниже.

public interface IA
{
  void DoA();
}

public interface IB
{
  void DoB();
}

public class A : IA
{
  public void DoA() { Console.WriteLine("A"); }
}

public class B : IB
{
  public void DoB() { Console.WriteLine("B"); }
}

public class MultipleInheritanceExample : IA, IB
{
  private IA m_A = new A();
  private IB m_B = new B();

  public void DoA() { m_A.DoA(); }
  public void DoB() { m_B.DoB(); }

}

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

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

public static class IAExtensions
{
  public static void Foo(this IA target)
  {
    target.DoA();
  }
} 

Это, конечно, имеет свои проблемы. На самом деле это не вызывает какого-либо наследования, что означает, что интерфейс IA на самом деле не имеет метода Foo. Это означает, что только код, импортирующий класс IAExtensions, может использовать методы из него. Другими словами, здесь нет полиморфизма.

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

1 голос
/ 12 августа 2010

Альтернативой в C # (и может существовать в Java, но я не Java-человек, поэтому я не знаю) являются интерфейсы.

public interface C
{
    int SomeMethodInC();
}

public class A
{
}

public class B : A, C
{
}

... in other class....
B someB = new B();
i someInt = someB.SomeMethodInC();

Это выглядит как множественное наследование, но это не так. Интерфейс C определяет подпись для someMethodInC, но не реализацию. Класс B должен будет реализовать someMethodInC.

В C # вы можете наследовать только от одного класса, но вы можете наследовать несколько интерфейсов. (То же самое на Яве, я думаю.)

В C # вы также можете присоединять реализации к интерфейсам, используя методы расширения.

public static class CExtensions
{
    public static int SomeExtensionToC(this C someC, int someInt)
    {
       return someInt * 2;
    }
}
... in code ...
B objB = new B();
y = objB.SomeExtensionToC(x);

И метод, и реализация SomeExtensionToC будут доступны любому классу, который наследует interface C. Обратите внимание, что и класс, и метод являются статическими, и что первый параметр включает ключевое слово «this» в отношении объекта, реализующего C. Некоторые части .NET Framework (например, LINQ) реализованы как методы расширения для IEnumerable<T>.

Почти как множественное наследование, без плохих частей. А методы расширения по-прежнему считаются частью интерфейса, поэтому могут рассматриваться как часть «контракта», присущего интерфейсу C.

0 голосов
/ 12 августа 2010

Ваше определение множественного наследования неверно.

На уровне ОО множественное наследование четко и четко определено.

И C ++, и Java поддерживают множественное наследование.

Проблема в том, что большинство программистов имеют абсолютно нулевые понятия OO / OOA / OOD, и все, что они знают, это детали реализации ООП.Отсюда их ошибочное мнение, что "наследование" является синонимом "наследования реализации" .

Однако это совершенно неверно .

Поскольку Java поддерживает множественное (интерфейсное) наследование, которое является реальной и единственной формой наследования, существующей на уровне Object-Oriented-Analysis / Object-Oriented-Design.

Show me любой OOD, полученный в результате OOA и использующий множественное наследование, и я могу без труда перевести его в OOP в Java, используя множественное наследование интерфейса (в качестве дополнительного бонуса в Java проблема "diamond" не существует).

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