Производный и базовый класс, могу ли я явно указать базовый класс?

public class SuperCar: Car
{
     public bool SuperWheels { get {return true; } }
}

public class Car 
{
     public bool HasSteeringWheel { get {return true;} }
}

Как я могу установить базовый класс для производного суперкара?

Например, я хочу просто установить базовый класс SuperCars следующим образом:

public void SetCar( Car car )
{
SuperCar scar = new SuperCar();
car.Base = car; 
}

В принципе, если у меня есть объекты Car, я не хочу вручную перебирать каждое свойство автомобиля, чтобы настроить объект SuperCar, что, как я думаю, является единственным способом, которым вы можете это сделать, но если вы можете сделать это по-другому, было бы ооочень лучше.


person Watson    schedule 28.01.2011    source источник
comment
Нет. Краткая причина: нет отдельного базового объекта. (object)this == (object)base всегда верно. Однако есть способы выполнить клонирование / копирование с помощью отражения (и других средств). Пожалуй, опишите, что действительно хотелось :)   -  person    schedule 28.01.2011
comment
Хотя вопрос не касается отражения (или конструктора копирования) как таковой, я добавил теги, чтобы, надеюсь, создать более интересный список связанных вопросов. Наслаждаться. (stackoverflow.com/questions/3072518/ выглядит особенно интересным и, возможно, дублирующим)   -  person    schedule 28.01.2011
comment
Я не так часто использую наследование, поэтому есть большая вероятность, что есть лучший способ выполнить то, что я на самом деле пытаюсь сделать. По сути, я использую службы wcf ria в winforms, но я использую пакет пользовательского интерфейса Janusys, который требует, чтобы я переводил элементы, созданные прокси-сервером службы, в ITypelist. Итак, я пытаюсь просто унаследовать тип, сгенерированный прокси-сервером службы, чтобы создать ItemCollection: List ‹proxyItem›, ItypedList   -  person Watson    schedule 28.01.2011
comment
@ Эрик Липперт: похоже, он ищет даже не наследования, а лучшего структурирования его объектов или его архитектуры.   -  person siride    schedule 28.01.2011
comment
Однако на первый взгляд это казалось самым простым делом. Мне нужны были все базовые свойства плюс 1 или 2 дополнительных свойства.   -  person Watson    schedule 28.01.2011
comment
Я читал об этом и был немного разочарован ответами. Я все еще немного не понимаю, почему вы не можете установить базовый класс для чего-то, что унаследовало этот класс. Конечно, вы не должны форсировать реализацию унаследованного класса, но если у вас есть реализация - почему бы не установить ее? Например, если вы создаете класс, унаследованный от обезьяны и гоночной машины, это не обезьяна или гоночная машина - понятно. Однако, если у вас есть реализация обезьяны и гоночной машины и вы хотите подключить эти реализации - почему бы и нет?   -  person Watson    schedule 07.10.2011
comment
И если вам нечего сказать полезного, просто ничего не говорите. Эрик Липперт ничего не добавил к этому разговору. Он не сказал, почему вам не следует этого делать или почему C # работает именно так, просто он сказал, и его авторитет достаточно высок - никаких объяснений не требуется. Пожалуйста, объясните и спасибо за рыбу.   -  person Watson    schedule 07.10.2011
comment
@ user190084: Я думаю, вы здесь немного лукавите. Эрик дал вполне разумное объяснение: C # не использует наследование прототипов. Он использует классическое наследование, которое используется только во время компиляции, что упрощает реализацию (для статически типизированного языка). Похоже, проблема действительно в другом. Я вижу, что вы объяснили реальный вариант использования. Возможно, вам следует отредактировать вопрос, указав эту информацию, и, возможно, вы получите более точные ответы.   -  person siride    schedule 18.10.2011
comment
Если бы Эрик сказал именно то, что вы только что сказали, я бы не стал делать дополнительных комментариев. Вы только что привели очень вескую причину, по которой в C # используется классическое наследование. Спасибо.   -  person Watson    schedule 03.11.2011


Ответы (7)


Я использую что-то вроде этого в подклассе, и у меня он отлично работает:

using System.Reflection;
.
.
.
/// <summary> copy base class instance's property values to this object. </summary>
private void InitInhertedProperties (object baseClassInstance)
{
    foreach (PropertyInfo propertyInfo in baseClassInstance.GetType().GetProperties())
    {
        object value = propertyInfo.GetValue(baseClassInstance, null);
        if (null != value) propertyInfo.SetValue(this, value, null);
    }
}
person vyengr    schedule 25.09.2013
comment
да. Это было прекрасно. - person Watson; 17.10.2013

Если я правильно понимаю ваш вопрос (и я не совсем уверен, что это так), вы можете получить желаемое поведение, выполнив что-то вроде этого:

class Car {
    public bool CarProperty { get; set; }
    // regular constructor
    public Car() {

    }
    // "copy" constructor
    public Car(Car c) {
        CarProperty = c.CarProperty;
    }
}

class SuperCar : Car {
    public bool SuperCarProperty { get; set; }
    // regular constructor
    public SuperCar() {
    }
    // "copy" constructor
    public SuperCar(Car c) : base(c) {
        SuperCar sc = c as SuperCar;
        if(sc != null) {
            SuperCarProperty = sc.SuperCarProperty;
        }
    }

Тогда вы можете сделать это:

public void SetCar(Car car) {
    SuperCar scar = new SuperCar(car);
}

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

Однако я должен спросить, какова ваша цель в этом?

person siride    schedule 28.01.2011
comment
Моя цель проста. По сути, в реальной жизни суперкар, вероятно, будет иметь сотни свойств. Допустим, я сейчас веду базу данных суперкаров. Теперь я хочу унаследовать от суперкаров, но я хочу передать базовый класс суперкаров, которые я уже создал, для удобства. Я не хочу вручную устанавливать 100 свойств, когда Я УЖЕ создал базовый тип. - person Watson; 28.01.2011
comment
Похоже, вам нужно разбить SuperCar на более мелкие объекты. Затем объекты, которые являются одинаковыми для SuperCars, могут быть разделены. - person siride; 28.01.2011
comment
Меня больше беспокоит мое понимание наследования в C #. Мне просто кажется, что если класс A является производным от класса B, вы должны иметь возможность установить B на A. Итак, если у вас есть экземпляр класса A, вы должны иметь возможность сказать A.B = new B (); - person Watson; 28.01.2011
comment
В мире моей мечты вы можете добавить к классу A вот так, чтобы открыть базу B: public B GetSetBase {get {return base; установить {base = value;}} - person Watson; 28.01.2011
comment
Я не думаю, что вы хорошо разбираетесь в наследовании. Наследование - это определение форм для набора объектов, а не конкретных деталей для конкретного объекта. Для последнего вы хотите использовать композицию. - person siride; 28.01.2011
comment
Но в данном случае у меня есть и то, и другое. У меня есть форма для набора объектов, а также конкретные детали. Что это за файл? - person Watson; 28.01.2011
comment
@ user190084: это файлы с использованием как наследования, так и композиции. Дело в том, что вы не можете установить базовый класс во время выполнения, и, честно говоря, это обычно не имеет смысла, если у вас нет языка, который использует утиную типизацию (и даже тогда это действительно опасно). - person siride; 29.01.2011
comment
Я изучу это дальше. Я очень ценю отзывы. Большое Вам спасибо. - person Watson; 29.01.2011

Это невозможно.

Вам нужно вручную установить свойства.

person SLaks    schedule 28.01.2011
comment
Допустим, у меня есть класс людей, и, конечно же, есть тысячи элементов данных, которые представляют этот класс. Класс person определяет десять тысяч свойств. Теперь у меня есть идентификатор человека, который ассоциируется с определенным классом людей, от которого я хочу унаследоваться, и создает класс Джона, унаследованный от человека. Теперь я знаю ID конкретного человека, которому хочу передать, и это будет база Джона. - person Watson; 28.01.2011
comment
Вы можете сделать обертку вместо наследования. - person SLaks; 28.01.2011

В целом много полезных комментариев. Я думаю, что краткий ответ был дан pst, и я думаю, что это правильно:

Нет. Краткая причина: нет отдельного базового объекта. (объект) this == (объект) база всегда истинна. Однако есть способы выполнить клонирование / копирование с помощью отражения (и других средств). Пожалуй, опишите, что действительно нужно

Так что его предложение использовать инструмент automapper также было невероятно полезным, и в основном это было то, что я искал.

person Watson    schedule 17.10.2011

Вы можете только копировать содержимое другого класса, но не устанавливать его напрямую. См. Пример ниже с использованием так называемого конструктора копирования.

class Car
{
    string model;
    public Car(string model) { this.model = model; }
    protected Car(Car other) { this.model = other.model; }
    string Model { get; set; }
}

class SuperCar : Car
{
    public SuperCar(Car car) : base(car) { }
    public SuperCar(string model) : base(model) { }
    bool IsTurbo { get; set; }
}

Ключ - это ключевое слово base() после объявления конструктора.

person John Alexiou    schedule 28.01.2011
comment
это интересно, но на самом деле это не решает проблему перебора 30 свойств, если я чего-то полностью не упускаю. - person Michael Sefranek; 27.03.2018
comment
Если требуется ручная установка свойств, то этот ответ лучше объясняет, как лучше всего использовать конструкторы копирования. - person John Alexiou; 27.03.2018

Прежде всего, каждый объект SuperCar отличается от другого. Наследование помогает определить общее поведение связанных объектов. Это не означает, что они являются одними и теми же объектами. Каждый объект типа имеет свой собственный процесс построения. Перед созданием дочернего объекта создается объект базового класса в соответствии с иерархией наследования. Если вы хотите использовать общее свойство для всех объектов SuperCar, вам необходимо поддерживать отдельный экземпляр объекта Car в экземпляре SuperCar, назначить общий объект автомобиля объекту автомобиля в SuperCar и переопределить свойства, производные от базового автомобиля. объект и перенаправить его в props. внутреннего объекта Автомобиль.

public class SuperCar: Car
{
     public bool SuperWheels { get {return true; } }

     Car carInstance = null;
     public void SetCar( Car car )
     {
         carInstance = car; 
     }
}

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

person this. __curious_geek    schedule 28.01.2011

Если вы хотите иметь больше контроля, чем копирование отраженных свойств, попробуйте применить шаблон Builder. T может быть любым классом, производным от BaseClass.

 public static T BuildNew<T>(BaseClass baseClass) where T : BaseClass, new()
 {
    return new T
    {
        Property1 = baseModel.Property1,
        Property2 = baseModel.Property2,
    };
 }
person Roman S    schedule 04.11.2017