Почему мы должны иметь класс Object в качестве базового класса для всех классов?

Пакет go-bindata выглядит так, как будто вас интересует.

https://github.com/go-bindata/go-bindata

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

13
задан JPReddy 25 June 2010 в 03:39
поделиться

7 ответов

Наличие однокорневой иерархии типов может быть полезно по-разному. В частности, до появления дженериков это был единственный способ работы чего-то вроде ArrayList . С дженериками он дает значительно меньше преимуществ - хотя я подозреваю, что он все еще может быть полезен в некоторых ситуациях. РЕДАКТИРОВАТЬ: Например, модель построения LINQ to XML очень "свободна" с точки зрения указания через объект ... но работает очень хорошо.

Что касается наследования из разных классов - вы получаете напрямую из одного класса, но он, в свою очередь, будет производным косвенно из другого, и так далее до Object.

Обратите внимание, что вещи, которые «имеют все объекты общего», такие как хэш-код, равенство и мониторы, считаются еще одним дизайнерским решением, в разумности которого я сомневаюсь. Без единой корневой иерархии эти проектные решения, возможно, не были бы приняты таким же образом;)

14
ответ дан 1 December 2019 в 19:49
поделиться

Тот факт, что каждый класс наследует объект, обеспечивается компилятором.
То есть, если вы напишете:

class A {}

Это будет компилироваться как:

class A : Object{}

Но если вы укажете:

class B : A {}

Object будет в иерархии B, но не напрямую - так что множественного наследования по-прежнему нет.

9
ответ дан 1 December 2019 в 19:49
поделиться

Что ж, множественное наследование объекта не применяется - вы можете думать об этом как:

«Если тип не имеет базового типа, тогда неявно внедрить Object ".

Таким образом, применяя правило ad-nauseam, все типы наследуются от объекта один раз и только один раз - поскольку внизу иерархии должен быть тип, не имеющий основы; и, следовательно, который будет неявно унаследован от Object .

Что касается того, почему эти языки / фреймворки имеют эту особенность, у меня есть несколько причин:

1) Подсказка в названии «Объектно-ориентированный». Все является объектом, поэтому все должно иметь в своей основе «объект» (или эквивалент), иначе принцип дизайна будет нарушен с самого начала.

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

3) Это означает, что вы можете избежать использования неприятных приведений типов, которые могут нарушить работу - например, (((int *) (void *)) value) - так как у вас есть хороший дружелюбный супертип для всего

Там, вероятно, гораздо больше, чем это - и за то время, которое мне потребовалось, чтобы написать это, было опубликовано 6 новых ответов; так что я оставлю это здесь и надеюсь, что люди лучше меня смогут объяснить более подробно и, возможно, лучше :)

2
ответ дан 1 December 2019 в 19:49
поделиться

У вас есть базовый класс Object, в том числе и потому, что у класса Object есть методы (например, в .NET, GetHashCode(), которые содержат общую функциональность, которую должен иметь каждый объект).

Множественное наследование действительно невозможно, но можно вывести класс A из класса B, потому что A может не выводиться напрямую из Object, но B выводится, поэтому все классы в конечном счете выводятся из Object, если зайти достаточно далеко в иерархии наследования класса.

1
ответ дан 1 December 2019 в 19:49
поделиться

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

Что касается второго вопроса, то вы просто выводите свой класс от другого класса; тогда он будет потомком этого класса, который, в свою очередь, является потомком Object. Никакого конфликта нет.

1
ответ дан 1 December 2019 в 19:49
поделиться

Вкратце

1) Класс Object определяет базовое состояние и поведение, которыми должны обладать все объекты, например, способность сравнивать себя с другим объектом, преобразовывать в строку, ждать переменную условия, уведомлять другие объекты об изменении переменной условия и возвращать класс объекта.

2) Вы можете иметь B расширять C, а A расширять B. A - дочерний класс B, а B - дочерний класс C. Естественно, A также является дочерним классом C.

.
3
ответ дан 1 December 2019 в 19:49
поделиться

Для сравнения давайте посмотрим на язык, который не использует единственный корневой класс - Objective-C. В большинстве сред Objective-C будут доступны три корневых класса (Object, NSObject и NSProxy), и вы можете написать свой собственный корневой класс, просто не объявляя суперкласс. На самом деле Object является устаревшим и существует только по причинам наследия, но это информативно, чтобы включить его в это обсуждение. Язык является duck typed, поэтому вы можете объявить тип переменной как "любой старый объект" (записывается как id), тогда даже не важно, какой корневой класс она имеет.

Хорошо, у нас есть все эти базовые классы. На самом деле, даже для того, чтобы компилятор и библиотеки времени выполнения могли куда-либо добраться, им необходимо некоторое общее поведение: все корневые классы должны иметь указатель ivar под названием isa, который ссылается на структуру определения класса. Без этого указателя компилятор не знает, как создать структуру объекта, а библиотека времени выполнения не знает, как узнать, к какому классу относится объект, каковы его переменные экземпляра, на какие сообщения он реагирует и так далее.

Поэтому, хотя Objective-C утверждает, что у него несколько корневых классов, на самом деле есть некоторое поведение, которое должны реализовывать все объекты. Таким образом, кроме названия, существует общий примитивный суперкласс, хотя и с меньшим API, чем java.lang.Object.

N.B. Как оказалось, и NSObject и NSProxy действительно предоставляют богатый API, подобный java.lang.Object, через протокол (как интерфейс Java). Большинство API, претендующих на работу с типом id (помните, это тип "любой старый объект"), на самом деле будут считать, что они отвечают на сообщения в протоколе. К тому времени, когда вам действительно нужно использовать объект, а не просто создавать его компилятором, оказывается полезным сложить все это общее поведение, такое как равенство, хэширование, описание строк и т.д., в корневой класс.

1
ответ дан 1 December 2019 в 19:49
поделиться