Задать вопрос
@borgez

C# — как организовать множественное наследование?

Есть Классы с наследованием, как сделать так, чтобы не выдавал в рантайме null для поля dvs а override не позволяет использовать наследуемый класс dvsDizel?

autoA
dvs null
dvs dvsDizel
a dvs


autoB
dvs null
dvs dvsBenzin
a dvs

Запускать в linqpad например
void Main()
{
	var a = new autoA();
	a.Dump();
	var b = new autoB();
	b.Dump();
}

// Define other methods and classes here
public class dvsCommon{
	public dvsCommon(){
		a="dvs";
	}
    public string a{get;set;}

}

public class dvsBenzin : dvsCommon{
	public dvsBenzin() : base(){
	}
}

public class dvsDizel : dvsCommon{
	public dvsDizel() : base(){	
	}
}

public  class autoCommon{
       public dvsCommon dvs {get;set;}

}

public class autoA : autoCommon{
	public autoA(){
		dvs = new dvsDizel();
	}
     public dvsDizel dvs {get;set;}

}

public  class autoB : autoCommon{
	public autoB(){
		dvs = new dvsBenzin();
	}
       public dvsBenzin dvs {get;set;}         

}
  • Вопрос задан
  • 3240 просмотров
Подписаться 2 Оценить Комментировать
Пригласить эксперта
Ответы на вопрос 4
FirstX
@FirstX
.net developer
Задача конечно жесть, действительно очень сложно понять конечную цель ваших манипуляций (а мотивацию для чего вы это делаете). Но немного теории на счет того, что тут происходит.

Есть AutoCommon и есть ряд наследников У AutoCommon есть свойство DSV, и у AutoA мы снова видим определение свойства DSV. В этот момент, компилятор неявно считает, что это абсолютно новое свойство, никак не связанное с родительским (каждый остается при своем свойстве). То есть то, что написано у вас на самом деле выглядит так

public class autoA : autoCommon{
	public autoA(){
		this.dvs = new dvsDizel();
	}
     public new dvsDizel dvs {get;set;}

}


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

Теперь когда мы делаем так:

AutoCommon auto = new AutoA();
WriteLine(auto.dsv.a);

Что мы видим? Правильно, ничего. Почему? Да потому что мы пытаемся обратиться к свойству, которое принадлежит родительскому классу, а мы его и не создавали никогда (точнее экземпляр объекта для свойства), мы создавали свойство дочернего объекта.

Перепишем пример так:

public class autoA : autoCommon{
	public autoA(){
		base.dvs = new dvsDizel();
	}
     public new dvsDizel dvs {get;set;}

}


Теперь мы создаем экземпляр объекта не для дочернего объекта, а именно для родителя.
После этого пример выше, выведет нам то, что вы видимо хотели, то есть строку с текстом.
НО при таком вызове:

AutoA auto = new AutoA();
WriteLine(auto.dsv.a);

Вы опять получите эксепшен с null. Почему ? Да потому что вы обращаетесь к свойству уже дочернего объекта, которое в этот раз мы оставили пустым)

Итого: вы имете 2 свойства в дочернем объекте (родительское и "свое") с одинаковым именем. Чтобы обратиться к родительскому используете base.* , чтобы обратиться к своему можно явно через this.*, либо this можно опустить.

public class autoA : autoCommon{
	public autoA(){
		base.dvs = new dvsDizel();
               this.dvs = base.dsv;
	}
     public new dvsDizel dvs {get;set;}

}


В данном варианте они теперь ссылаются на один и тот же объект, но обращаясь по родительскому типу данных вы сможете получать общие методы dsv, а если сделаете приведение типов к конкретному классу AutoA, то сможете вызывать методы DvsDizel.
Ответ написан
@Kokcuk
Ну в данном случае было бы не плохо вот так сделать, если правильно понял:
public interface IAuto
{
         IEngine Engine {get;}
}
public AutoA: IAuto
{
         Engine { return new Dizel(); }
}
public interface IEngine
{
          ....
}
public class Dizel : IEngine
{
         ....
}
Ответ написан
@DancingOnWater
В С# множественное наследование запрещено.

Какая задача стоит?
Ответ написан
@gleb_kudr
Я слабо понял, что вы хотите, но чую, что тут нужно использовать коллекции и реляционные отношения, а не классы. Ваша модель просто не ложится на ООП-шное наследование.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы