Derived and base class, can I set the base explicitly?
Asked Answered
W

7

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

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

How can I set the base class for the derived Supercar?

For example, I want to simply set SuperCars base class like this:

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

Basically, if I have Car objects, I do not want to manually iterate through every property of the car in order to setup the SuperCar oject, which I think is the only way you can do it but if you can do it the other way it would be sooo much better.

Worst answered 28/1, 2011 at 1:4 Comment(9)
No. Short reason: There is no separate base object. (object)this == (object)base is always true. There are ways to perform cloning/copying by reflection (and other means) though. Perhaps describe what is really wanted :)Noreen
While the question doesn't ask about reflection (or a copy-constructor) as it is, I added the tags to hopefully generate a more interesting list of related questions. Enjoy. (#3073018 looks particularly interesting, and perhaps duplicative)Noreen
I don't use inheritance that much, so there is a great chance there isa better way to accomplish what I am actually trying to do. Basically, Im using wcf ria services in winforms, but I am using Janusys ui suite which requires me to translate the items created by service proxy to a ITypelist. So I am trying to simply inherit the type generated by a service proxy in order to create an ItemCollection : List<proxyItem>, ItypedListWorst
@Eric Lippert: it sounds like it's not even inheritance he's after, but better structuring of his objects or his architecture.Pulmonary
Yet, on the surface it seemed like the easiest thing to do. I needed all the base properties plus 1 or 2 additional properties.Worst
I was reading back on this and was slightly disappointed by the responses. I'm still slightly confused as to why you shouldn't be able to set a base class on something that inherated that class. Sure, you shouldn't force implementation on an inherated class, but if you happen to have an implementation - why not be able to set it? For example, if you're creating a class that inherits from a monkey and race car, it isn't a monkey or a race car - understood. However, if you happen to have an implementation of a monkey and race car and would like to plug those implementations in - why not?Worst
And if you have nothing useful to say just dont say anything. Eric Lippert added nothing to this conversation. He didn't say why you shouldn't do it or why c# worked in this way, just that it did and his authority is good enough - no explanation needed. Please explain and thanks for all the fish.Worst
@user190084: I think you are being a bit disingenuous here. Eric gave a perfectly reasonable explanation: C# does not use prototype inheritance. It uses classical inheritance, which is a compile-time feature only, which makes it easier to implement (for a statically typed language). It sounds like the problem is really elsewhere. I see that you have explained the actual use case. Perhaps you should edit the question with that info and maybe you'll get better answers.Pulmonary
Had Eric said exactly what you just said, I would not have made my additional comments. You just gave an extremely good reason why c# uses classical inheritance. Thank you.Worst
W
1

Overall a lot of helpful comments. I think the short answer was given by pst and I think this is correct:

No. Short reason: There is no separate base object. (object)this == (object)base is always true. There are ways to perform cloning/copying by reflection (and other means) though. Perhaps describe what is really wanted

So, his suggestion of using the automapper tool was also incredibly useful and was basically what I was looking for.

Worst answered 17/10, 2011 at 23:32 Comment(0)
T
15

I use something like this in the subclass and it works fine for me:

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);
    }
}
Tympanitis answered 25/9, 2013 at 16:16 Comment(1)
Yes. This is was perfect.Worst
P
4

If I'm understanding your question correctly (and I'm not entirely sure that I am), then you can sort of get the behavior you want by doing something like this:

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;
        }
    }

Then you can do this:

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

Note that you have to be very careful in your "copy" constructor not to copy properties in such a way that two objects share the same members (references) when they should not.

I have to ask, though, what your goal is with this?

Pulmonary answered 28/1, 2011 at 1:22 Comment(8)
My goal is simple. Basically, in real life Supercar would probably have 100's of properties. So lets say I now maintain a database of supercars. Now, I want to inherit from supercars but I want to pass the base class of the supercars I have already created for sheer conveniance. I dont want to manually set 100 properties when I HAVE ALREADY created the base type.Worst
Sounds like you need to break up SuperCar into smaller objects. Then objects that are the same between SuperCars can be shared.Pulmonary
I'm more concerned with my understand of inheritance in c#. It just seems to me, that if class A derives from class B, you should be able to set B on A. So if you have an instance of an A class you should be able to say A.B = new B();Worst
In my dream world you can add to class A like this to expose base B: public B GetSetBase { get { return base; set { base = value;} }Worst
I don't think you understand inheritance very well. Inheritance is about defining forms for a set of objects, not specific details for a specific object. For the latter, you want to use composition.Pulmonary
Yet in this case, I have both. I have a form for a set of objects and I also have the specific details. What does that file under?Worst
@user190084: it files under using both inheritance and composition. The fact is, you can't set the base class at runtime and to be perfectly honest, it generally doesn't make sense unless you have a language that uses duck-typing (and even then, it's real dangerous).Pulmonary
I will look into this further. I really appreciate the feedback. Thank you very much.Worst
D
2

This is not possible.

You need to manually set the properties.

Disquieting answered 28/1, 2011 at 1:5 Comment(2)
Lets say I have a person class, and of course there are thousands of data items that represent the person class. The person class defines ten thousand properties. Now, I have a person id that associates to particular person class I want to derive from and create a "John" class inheritated from person. Now I know a particular person ID I want to pass in and that will be the base of "John".Worst
You can make a wrapper instead of using inheritance.Disquieting
K
2

You can only copy the contents of another class, but not set it directly. See example below using what is called a copy constructor.

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; }
}

The key is the keyword base() after the constructor declaration.

Kila answered 28/1, 2011 at 2:33 Comment(2)
that is interesting, but it doesn't really address the issue of iterating through 30 properties unless I am totally missing something.Couplet
If manual setting of properties is desired, then this answer explains it better on how to best use copy constructors.Kila
W
1

Overall a lot of helpful comments. I think the short answer was given by pst and I think this is correct:

No. Short reason: There is no separate base object. (object)this == (object)base is always true. There are ways to perform cloning/copying by reflection (and other means) though. Perhaps describe what is really wanted

So, his suggestion of using the automapper tool was also incredibly useful and was basically what I was looking for.

Worst answered 17/10, 2011 at 23:32 Comment(0)
Z
0

First of all, Each SuperCar object is different from the other. Inheritance helps you define common behaviour of related objects, It does not mean they are the same objects. Each object of a type has its own construction process. Before a child object is created, the object of base class is created as per the inheritance hierarchy. If you wish to use a common property for all SuperCar objects, you'll need to maintain a seperate instance of the Car object within SuperCar instance, assign the common car object into the car object in SuperCar and override the properties derived from the base Car object and redirect it to props. of internal Car object.

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

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

But I stiill believe, there's something wrong with this design the way you want to do it. If you can let us know the larger picture as to why you want to do this, we may come up with better design to address your requirement.

Zebec answered 28/1, 2011 at 1:26 Comment(0)
S
0

If you would like to have more control than copy reflected properties try to apply Builder pattern. T can be any class derived from BaseClass.

 public static T BuildNew<T>(BaseClass baseClass) where T : BaseClass, new()
 {
    return new T
    {
        Property1 = baseModel.Property1,
        Property2 = baseModel.Property2,
    };
 }
Selfdeprecating answered 4/11, 2017 at 4:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.