Я давно задаю себе этот вопрос. Думал выложить. C# не поддерживает множественное наследование (это факт). Все классы, созданные в C#, являются производными от класса Object (опять же факт).
Итак, если C# не поддерживает множественное наследование, как мы можем расширить класс, даже если он уже расширяет класс Object?
Иллюстрируя примером:
Мы можем использовать методы класса объектов в A после шага 3. Так происходит переход к многоуровневому наследованию. Если это так, то
Кто-нибудь может объяснить?





Вы путаете множественное наследование с деревом наследования. Вы можете унаследовать от чего-то другого, кроме Object. Просто Объект сидит там, на вершине вашего дерева. И кто-то может унаследовать ваш класс, но поскольку Object все еще находится наверху, этот класс также будет наследовать от объекта. Ваше «многоуровневое» наследование - это не множественное наследование.
Множественное наследование - это когда вы наследуете от двух разных деревьев, и .Net действительно поддерживает это через интерфейсы.
Это просто семантика. Реализация интерфейса является - слабая форма наследования.
Замените дерево «ветвью дерева» и пропустите часть о реализации интерфейсов, являющихся наследованием. Реализация интерфейса просто означает, что ваш класс гарантирует, что он определит подпись. Вы не наследуете код от интерфейса. Но, вы сказали "в некотором роде", так что, я думаю ...
Я должен поддержать Марка в этом. Важно отличать реализацию от расширения. Реализация интерфейса означает согласие с контрактом. Это не наследование в смысле слова ООП.
Кроме того, структуры реализуют интерфейсы, но не наследуют. Типы значений «наследуются», а не «наследуют» их суперкласс (System.ValueType). Из-за этого реализация интерфейса на самом деле совсем не похожа на наследование.
Реализация интерфейса не является наследованием, если только его нельзя унаследовать от человека без активов.
Нижеприведенный.
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.
В конечном итоге класс всегда будет наследовать от объекта, даже если вы укажете свой собственный базовый класс.
Да - в конечном итоге - но не напрямую. Думаю, я объяснил это в последнем абзаце.
Ответ Джоэла правильный. Существует разница между множественным наследованием и деревом наследования (или цепочкой производных). В вашем примере вы фактически показываете дерево наследования: один объект наследует (наследует) от другого объекта, расположенного выше в дереве. Множественное наследование позволяет одному объекту наследовать от нескольких базовых классов.
Возьмем, например, следующее дерево:
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. Спасибо за разъяснение.
Класс в C# может иметь только одного родителя, но может иметь несколько предков. Вы можете реализовать несколько интерфейсов, но это означает только то, что ваш класс соглашается реализовать сигнатуры, определенные этими интерфейсами. Фактически вы не наследуете какие-либо функции от этих интерфейсов.
Один из способов взглянуть на это так: C# имеет наследование дерево, а C++ (или другие языки множественного наследования) имеет наследование решетка.
C# не поддерживает множественное наследование, но поддерживает несколько интерфейсов. Вы по-прежнему можете наследовать только от 1 объекта.