2010-08-12 2 views
2

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

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

Ok вот вопрос:

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

//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, который является методом, определенным в этом классе.

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

Спасибо.

+1

Можете ли вы опубликовать образец кода, который вы пытаетесь сделать в «Объявив эти классы, как указано выше (в NetBeans), я вижу, что после создания объекта класса C (в основном) я не могу вызвать методFromC»? – Bruno

+11

Это не пример множественного наследования, это просто обычное наследование, как это делали боги. Множественное наследование, которое java пустоты - это то место, где у вас есть классы Ba и Bb, которые оба реализуют A, а затем класс C, который реализует как Ba, так и Bb, что приводит к структуре в форме алмаза. Путаница устанавливает, когда Ba и Bb переопределяют общедоступный метод m(), который затем вызывает C. Поскольку никогда не определено, какую реализацию m() вызывается, результаты могут быть неожиданными. Вот почему был сделан выбор дизайна только для реализации одного типа. – mikek

+0

Я бы не сказал, что это запрещено * в Java и C#, он просто не реализован на этих языках (по причинам, которые mikek заявляет) – Kris

ответ

-1

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

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

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

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

Однако это совершенно неправильно.

Поскольку Java поддерживает множественное (интерфейсное) наследование, которое является реальной и единственной формой наследования, которая существует на уровне объектно-ориентированного анализа/объектно-ориентированного проектирования.

Покажите мне любой ООД в результате чего из ООА и использует множественное наследование, и я могу перевести его чисто ООП в Java, используя множественное наследование интерфейса (как дополнительный бонус в Java проблема «алмаз» не существует).

+0

Однако обратите внимание, что по правде и правдоподобности мой ответ вряд ли будет хорошо принят на сайте типа SO, который полностью фокусируется на деталях реализации и часто посещается программистами, которые в большинстве своем полностью не знают о большей картине. Они изучали OO, скажем, при изучении Java и были рассказаны в этом процессе бесчисленными совершенно неправильными источниками, что Java поддерживает только одно наследование. Не ожидайте, что эти люди будут видеть свет и передумать :) – NoozNooz42

+0

Расширение интерфейсов никоим образом не представляет собой множественное наследование. Никакие детали реализации никогда не выводятся из интерфейса, это просто спецификация того, что класс должен содержать (и реализовать). Но если вы придерживаетесь иного мнения, не стесняйтесь разъяснять. – mikek

+0

@mikek: разумеется, расширение от нескольких интерфейсов представляет собой MI (на забавном sidenote, Java не получилось так: вы можете написать * интерфейс A расширяет B, C *. И я специально объяснил, почему в моем ответе «наследование нескольких интерфейсов «это множественное наследование». Вы серьезно запутываете «повторное использование кода» и «наследование». Обратите внимание, что все, что вы думаете, не может быть выполнено и, следовательно, не является MI, когда расширение от нескольких интерфейсов Java действительно может быть выполнено просто с помощью делегирования . Еще раз: покажите мне ** ЛЮБОЙ ** OOA/OOD с использованием MI, который нельзя тривиально портировать на Java с использованием наследования нескольких интерфейсов ... – NoozNooz42

7

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

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

Является действительным, но

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

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

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

+0

, но в NetBeans я не могу (он не показывает, что он доступен) c.methodFromC(); Зачем? –

+0

любое обновление о том, почему я не могу вызвать c.methodFromC()? –

+2

С кодом, который вы сейчас опубликовали, я не понимаю, почему возникает проблема. Вы пытались на самом деле ввести метод, чтобы узнать, компилируется ли код? Автозаполнение и компиляция не всегда одно и то же! В противном случае, дважды проверяйте модификаторы доступа (сделайте все общедоступным) и дважды проверьте, используете ли вы нижний регистр c, т. Е. 'C.methodOnC()'. Если C. верхний регистр t не будет работать, поскольку это будет означать статический метод. – mdma

6

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

class A {} 
class B {} 

class C extends A, B {} 

Что запрещено, если вы не кодирования в

1

C++ альтернатива в 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# вы можете наследовать только один класс, но вы можете наследовать несколько интерфейсов. (То же самое на Java, я думаю.)

В 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 (LINQ, как пример) реализованы как методы расширения до IEnumerable<T> ,

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

+0

Чтобы подтвердить, да Интерфейсы также существуют в Java с очень похожим синтаксисом и реализацией. http://stackoverflow.com/questions/3355408/explaining-interfaces-to-students/3361740#3361740 Динамические языки предлагают другие способы достижения множественного наследования. – JulesLt

2

Это не множественное наследование. И вы правы. 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(); } 

} 

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

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

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

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

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

Смежные вопросы