Множественное наследование в Ruby, Java и т. Д. - PullRequest
0 голосов
/ 21 сентября 2011

Это может звучать глупо, но если каждый класс неявно расширяет класс Object и ему разрешается расширять еще один класс, как это не множественное наследование? С точки зрения пользователя можно утверждать, что они не поддерживают множественное наследование, потому что пользователю не разрешено расширять более одного класса. Тем не менее, языки, кажется, имеют внутреннюю поддержку множественного наследования, которое просто не доступно пользователю, вероятно, для простоты. Имею ли я смысл?

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

Ответы [ 4 ]

7 голосов
/ 21 сентября 2011

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

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

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

Типичный способ обойти это ограничение, поэтому у вас есть интерфейсы в Java и включенные ("mixin") модули в Ruby.

2 голосов
/ 21 сентября 2011

Ситуация, которую вы описали, является просто чистым наследованием, она не имеет ничего общего с множественным наследованием. Например, в Java у нас есть Integer, который наследуется от Number, а Number наследуется от Object.

Стандартным примером языка с множественным наследованием является C ++

class A { };
class B { };
class C { };
class X : public A, private B, public C { };

В то время как в Java у нас есть

class A { }
class B extends A { }
class C extends B { }
class X extends C { }

С точки зрения множественного наследования Ruby похож на Java (у классов в ruby ​​может быть только один предок). Однако Ruby предоставляет различные механизмы, которые «действуют как» множественное наследование, то есть модули

# class XX inherits from CC
class AA 
end
class BB < AA
end
class CC < BB
end
class XX < CC
end

# class X mixin A,B,C modules
module A end
module B end
module C end
class X 
    include A
    include B
    include C
end

В Ruby (аналогично Java) класс AA имеет предка по умолчанию (цепочка наследования зависит от версии Ruby)

X.ancestors
[X, C, B, A, Object, Kernel, BasicObject]
XX.ancestors
[XX, CC, BB, AA, Object, Kernel, BasicObject]
1 голос
/ 21 сентября 2011

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

В таких языках, как Java, где множественное наследование не разрешено, идентичные члены просто переопределяются членом в дочернем классе.

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

0 голосов
/ 21 сентября 2011

Все ссылочные типы в Java - это java.lang.Object, как вы заметили.

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

Таким образом, вы можете быть абсолютно правы, когда говорите, что пользовательские типы в Java получают реализацию как от java.lang.Object, так и от расширенных суперклассов, но это считается единичным наследованием реализации, поскольку разработчик может расширять только один класс реализации.

Вы обсуждаете семантику. Вы не можете расширить несколько реализаций в Java.

Но вы можете реализовать несколько интерфейсов.

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