Почему нам нужен класс Object как базовый класс для всех классов?
Либо на С#, либо на Java или на любом другом языке, который следует за концепциями oops, как правило, для него по умолчанию используется "Object" как суперкласс. Зачем нам нужен Object как базовый класс для всех классов, которые мы создаем?
Если множественное наследование невозможно на языке С# или Java, как мы можем получить наш класс из другого класса, если он уже получен из класса Object. Этот вопрос может показаться глупым, но хотел бы узнать мнение экспертов по этому поводу.
Ответы
Ответ 1
Наличие иерархии с одним корневым именем может быть удобным для разных целей. В частности, до того, как появились дженерики, это был единственный способ работать с чем-то вроде ArrayList
. С дженериками значительно меньше преимуществ - хотя он может быть полезен в некоторых ситуациях, я подозреваю. EDIT: В качестве примера, модель построения LINQ to XML очень "свободна" с точки зрения определения через object
... но она работает очень хорошо.
Как для получения из разных классов - вы получаете непосредственно из одного класса, но это, в свою очередь, будет происходить косвенно с другого, и так далее до Object.
Обратите внимание, что вещи, которые "все объекты имеют вместе", такие как хэш-код, равенство и мониторы, считаются еще одним дизайнерским решением, которое я бы поставил под сомнение. Без единой корневой иерархии эти проектные решения, возможно, не были бы сделаны одинаково;)
Ответ 2
Тот факт, что каждый класс наследует объект, обеспечиваемый компилятором.
Это означает, что вы пишете:
class A {}
Он будет компилироваться следующим образом:
class A : Object{}
Но если вы заявите:
class B : A {}
Object
будет находиться в иерархии B
, но не напрямую - так что до сих пор нет множественного наследования.
Ответ 3
Короче
1) Класс Object определяет основное состояние и поведение, которые должны иметь все объекты, такие как способность сравнивать себя с другим объектом, преобразовывать в строку, ждать в переменной условия, уведомлять другие объекты, переменная условия изменилась и возвращает класс объекта.
2) У вас может быть B расширение C, а A - расширение B. A - это дочерний класс B, а B - дочерний класс C. Естественно, что A также является дочерним классом C.
Ответ 4
Ну, множественное наследование Object
не применяется - вы можете думать об этом как:
"Если тип не имеет базового типа, то неявно вставляйте Object
".
Таким образом, применяя правило ad-nauseam, все типы наследуют от объекта один раз и один раз - поскольку в нижней части иерархии должен быть тип, который не имеет базы; и поэтому он неявно наследует от Object
.
Что касается того, почему эти языки/структуры имеют это как функцию, у меня есть несколько причин:
1) Ключ в названии "Объектно-ориентированный". Все является объектом, поэтому все должно иметь "Объект" (или эквивалент) в нем, иначе принцип дизайна будет нарушен с момента выхода.
2) Позволяет фреймворку предоставлять привязки для общих операций, которые все типы должны/должны будут поддерживать. Такие, как генерация хеш-кода, вывод строки для отладки и т.д. И т.д.
3) Это означает, что вы можете не прибегать к неприятным типам бросков, которые могут сломать материал - например, (((int *)(void*))value)
- поскольку у вас есть хороший дружественный супертип для всего
Там, вероятно, загружается больше, чем это - и в то время, когда мне понадобилось писать, было опубликовано 6 новых ответов; поэтому я оставлю его там и надеюсь, что лучше людей, чем я могу объяснить более подробно и, возможно, лучше:)
Ответ 5
Относительно первой части вашего вопроса, как классы получают общие свойства и методы. Это также то, как мы можем иметь строго типизированные параметры для функций, которые могут принимать любой объект.
Что касается второго вопроса, вы просто получаете свой класс из другого класса; он будет потомком этого класса, который, в свою очередь, является потомком Object. Нет конфликта.
Ответ 6
У вас есть базовый класс Object, потому что среди других, поскольку класс Object имеет методы (например, в .NET, GetHashCode()
, которые содержат общую функциональность, которую должен иметь каждый объект).
Множественное наследование действительно невозможно, но можно получить класс A из класса B, потому что A не может непосредственно выводиться из Object, но B делает, поэтому все классы в конечном счете происходят из Object, если вы достаточно далеко продвигаетесь в класса ".
Ответ 7
Просто чтобы сравнить, давайте взглянем на язык, который не применяет один корневой класс - Objective-C. В большинстве сред Objective-C будут доступны три корневых класса (Object
, NSObject
и NSProxy
), и вы можете написать свой собственный корневой класс, просто не объявляя суперкласс. Фактически Object
устарел и существует только по причинам, связанным с наследием, но он информативен, чтобы включить его в это обсуждение. Язык утка напечатана, поэтому вы можете объявить тип переменной как "любой старый объект" (написанный как id
), тогда даже не имеет значения, какой у него класс корня.
ОК, поэтому у нас есть все эти базовые классы. На самом деле, даже для библиотек компилятора и среды выполнения, которые могут быть в любом месте, им нужно некоторое общее поведение: у корневых классов должен быть указатель ivar, называемый isa
, который ссылается на структуру определения класса. Без этого указателя компилятор не знает, как создать структуру объекта, а библиотека времени выполнения не знает, как узнать, какой класс является объектом, каковы его переменные экземпляра, какие сообщения он отвечает и т.д.
Итак, хотя Objective-C утверждает, что имеет несколько корневых классов, на самом деле существует некоторое поведение, которое должны реализовать все объекты. Таким образом, во всем, кроме имени, действительно существует обычный примитивный суперкласс, хотя и с меньшим API, чем java.lang.Object
.
N.B. так как это происходит, как NSObject
, так и NSProxy
предоставляют богатый API, похожий на java.lang.Object
, через протокол (например, интерфейс Java). Большинство API, которые утверждают, что имеют дело с типом id
(помните, что тип "любой старый объект" ) фактически предполагает, что он отвечает на сообщения в протоколе. К тому времени, когда вам действительно нужно использовать объект, а не просто создавать его с помощью компилятора, оказывается полезным сбрасывать все это общее поведение, такое как равенство, хеширование, описания строк и т.д. В корневой класс.
Ответ 8
Ну, множественное наследование - совершенно другая игра с мячом.
Пример множественного наследования: -
class Root
{
public abstract void Test();
}
class leftChild : Root
{
public override void Test()
{
}
}
class rightChild : Root
{
public override void Test()
{
}
}
class leafChild : rightChild, leftChild
{
}
Проблема здесь в том, что leafChild наследует Test of rightChild и leftChild. Итак, случай противоречивых методов. Это называется проблемой алмаза.
Но когда вы используете объект как суперкласс, иерархия выглядит следующим образом: -
class Object
{
public abstract void hashcode();
//other methods
}
class leftChild : Object
{
public override void hashcode()
{
}
}
class rightChild : Object
{
public override void hashcode()
{
}
}
Итак, здесь мы выводим оба класса из Object, но это конец.
Ответ 9
Он действует как шаблон для всех объектов, которые будут извлекаться из него, поэтому по умолчанию для каждого объекта предоставляется какая-то общая функциональность. Например, клонирование, хэш-код и блокировка объектов и т.д.