Одиночное наследование в C# - объектный класс?

Я давно задаю себе этот вопрос. Думал выложить. C# не поддерживает множественное наследование (это факт). Все классы, созданные в C#, являются производными от класса Object (опять же факт).

Итак, если C# не поддерживает множественное наследование, как мы можем расширить класс, даже если он уже расширяет класс Object?

Иллюстрируя примером:

  1. class A: object - Создан класс A.
  2. class B: object - Создан класс B.
  3. класс A: B - это снова поддерживается. Что происходит с более ранней ассоциацией с возражением.

Мы можем использовать методы класса объектов в A после шага 3. Так происходит переход к многоуровневому наследованию. Если это так, то

  1. класс A: B
  2. класс C: B
  3. класс A: C - я должен иметь доступ к методам класса B в A. Что не так?

Кто-нибудь может объяснить?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
8
0
8 522
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Вы путаете множественное наследование с деревом наследования. Вы можете унаследовать от чего-то другого, кроме Object. Просто Объект сидит там, на вершине вашего дерева. И кто-то может унаследовать ваш класс, но поскольку Object все еще находится наверху, этот класс также будет наследовать от объекта. Ваше «многоуровневое» наследование - это не множественное наследование.

Множественное наследование - это когда вы наследуете от двух разных деревьев, и .Net действительно поддерживает это через интерфейсы.

C# не поддерживает множественное наследование, но поддерживает несколько интерфейсов. Вы по-прежнему можете наследовать только от 1 объекта.

Mark Ingram 10.10.2008 18:05

Это просто семантика. Реализация интерфейса является - слабая форма наследования.

Joel Coehoorn 10.10.2008 18:07

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

tvanfosson 10.10.2008 18:07

Я должен поддержать Марка в этом. Важно отличать реализацию от расширения. Реализация интерфейса означает согласие с контрактом. Это не наследование в смысле слова ООП.

Jason Jackson 10.10.2008 18:10

Кроме того, структуры реализуют интерфейсы, но не наследуют. Типы значений «наследуются», а не «наследуют» их суперкласс (System.ValueType). Из-за этого реализация интерфейса на самом деле совсем не похожа на наследование.

Jeffrey L Whitledge 10.10.2008 18:27

Реализация интерфейса не является наследованием, если только его нельзя унаследовать от человека без активов.

Ryan Lundy 10.10.2008 19:39

Нижеприведенный.

public class A : B
{

}

public class B : C
{
    public int BProperty { get; set; }
}

public class C
{
    public int CProperty { get; set; }
}

public class Test
{
    public void TestStuff()
    {
        A a = new A();

        // These are valid.
        a.CProperty = 1;
        a.BProperty = 2;
    }

}

Это действительно так. В этом случае объект является базой для C.

Все классы в конечном счете являются производными от Object.

public class A

неявно эквивалентен

public class A : System.Object

Когда вы происходите из другого класса

public class A : B

где

public class B : System.Object

B становится родительским классом, а Object - классом прародителя.

И так далее.

Таким образом, это родительский класс, прародитель, прадедушка и т. д. Для всех остальных классов.

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

Класс наследуется от объекта если вы не укажете базовый класс. Таким образом:

class C {}

такой же как

class C : Object {}

Однако если вы укажете базовый класс, он будет унаследован от этого класса вместо Object. Таким образом,

class B : C {}

B напрямую наследуется от C, а не от Object. Другой пример,

class A : B {}

В этом случае A наследуется от B вместо Object. Подводя итог, в этой иерархии:

class C {}
class B : C {}
class A : B {}

Класс A является производным от B, который является производным от C. Таким образом, класс A косвенно является производным от C, потому что B является производным от C. C также является производным от Object, который явно не указан, но присутствует по умолчанию. Таким образом, A также косвенно является производным от Object.

В конечном итоге класс всегда будет наследовать от объекта, даже если вы укажете свой собственный базовый класс.

Scott Dorman 10.10.2008 18:22

Да - в конечном итоге - но не напрямую. Думаю, я объяснил это в последнем абзаце.

jop 10.10.2008 19:02
Ответ принят как подходящий

Ответ Джоэла правильный. Существует разница между множественным наследованием и деревом наследования (или цепочкой производных). В вашем примере вы фактически показываете дерево наследования: один объект наследует (наследует) от другого объекта, расположенного выше в дереве. Множественное наследование позволяет одному объекту наследовать от нескольких базовых классов.

Возьмем, например, следующее дерево:

public class BaseClass { }

public class SpecialBaseClass : BaseClass {}

public class SpecialtyDerivedClass : SpecialBaseClass {}

Это совершенно верно и говорит о том, что SpecialtyDerivedClass наследуется от SpecialBaseClass (родительский SpecialtyDerivedClass), который, в свою очередь, является производным от BaseClass (прародитель SpecialtyDerivedClass).

В соответствии с идеей множественного наследования пример будет выглядеть так:

public class BaseClass { }

public class SpecialBaseClass {}

public class SpecialtyDerivedClass : BaseClass, SpecialBaseClass {}

Это запрещено в .NET, но в нем говорится, что SpecialityDerivedClass наследуется как от BaseClass, так и от SpecialBaseClass (которые являются родителями).

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

public class BaseClass { }

public interface ISpecialBase {}

public interface ISpecialDerived {}

public class SpecialtyDerivedClass : BaseClass, ISpecialBase, ISpecialDerived {}

Это говорит о том, что SpecialtyDerivedClass наследуется от BaseClass (его родительский), а также ISpecialBase и ISpecialDerived (также родительский, но больше похожий на приемных родителей, поскольку интерфейсы не могут определять функциональность).

Мое замешательство заключалось в том, что я не смог увидеть, что класс System.Object становится прародителем после наследования A: B. Спасибо за разъяснение.

Rajeshwaran S P 10.10.2008 19:48

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

Один из способов взглянуть на это так: C# имеет наследование дерево, а C++ (или другие языки множественного наследования) имеет наследование решетка.

Другие вопросы по теме