Link to home
Start Free TrialLog in
Avatar of keyd
keyd

asked on

C# inheritance. base object initialization

Hi,

I have the following class, the Base that i cannot change and a Child that needs to initialize it's Base part.

class Base // cannot change this class
{
    public int a1 { get; set; }
    public int a2 {get; set; }
    etc..,
}

class Child : Base
{
    public Child( Base obj )
    {
         //question how can i initialize Child's Base part without explicitly assigning every property
    }
}

Thanks.
Avatar of abel
abel
Flag of Netherlands image

You can do that like so:



class Child : Base
{
    public Child( Base obj ) : base(obj)
    {
         /// your additional initialization
    }
}

Open in new window

Note that you are not obliged to call the constructor with the same signature. If you want to call the default constructor of the Base class, you can do it like this (note lowercase of "base" which is a keyword and not your classname):

class Child : Base
{
    public Child( Base obj ) : base()
    {
         /// your additional initialization
    }
}

Open in new window

Avatar of keyd
keyd

ASKER

Sorry i guess i wasn't too clear.
The problem is that i cannot change the base class, and also this is not a matter of Child construction, but initialization of base part. The Child class might as well has:

class Child : Base
{
    public Child() { }

    public InitBase( Base objBase )
    {
       //initialize the base part here
    }
}
You can only initialize a base class in a constructor. That's mandated by the language C#. If you want to call the constructor from another spot, you'll have to use the aggregator pattern, which means you'll have to rebuild the whole object.

Sorry to give you bad news, but it is simply not possible to initialize something on another spot when it is supposed to already have been initialized (recall that the base class constructor  (Base) is called automatically before the inheriting class (Child) constructor is called, so there really is no other way here and is defined by the language).
In addition, you already define it yourself with the declaration:

public InitBase( Base objBase )

which means "give the public method 'initBase' an object of type Base, going by the name 'objBase'. Whenever you call this method, you can only call it with an object of type Base. And an object can only be an object after it is initialized. So either way, the object objBase has to be initialized for the InitBase to work, prior to calling the method.

Again, this is mandated by the language C# (or VB, or any object oriented language like Java, Python, Ruby, Eiffel).
Avatar of keyd

ASKER

I guess i used initialize word wrong.
I'm talking about setting.
Generally i was asking if it is possible to have something like this

void SetBase( Base obj )
{
    (this as Base) = obj; // just an example
    // so to not write something like
    this.a1 = obj.a1;
    this.a2 = obj.a2;
    etc...
}
yes, you can access the settings of the base object by using the base keyword. Do not use a base object as parameter:

void SetBase(  )
{
    this.a1 = base.a1;   // refers to the setting of the parent object Base
    this.a2 = base.a2;   // refers to the setting of the parent object Base
}
Avatar of keyd

ASKER

abel, that's exactly what i'm trying to avoid here :-)
NOT have all the properties assigned one by one. I don't care about base keyword.
You might be able to do this if A is a singleton class or a class factory


    class A : B
    {
        static A _instance;
        public
        A (B obj) 
        {
        }
        static void Init( B obj )
        {
           _instance = new A(obj);
        }
    }
 
    class B 
    {
        public
            int a;
 
        public B() { }
    };

Open in new window

> NOT have all the properties assigned one by one. I don't care about base keyword.

well, I understand that, but it is "either/or". You simply cannot call the constructor after an object is instantiated, sorry, that is already done at that stage.

I'm not sure what you are after, but it is possible that another approach might suit you:

  • Using .NET it is possible to set properties dynamically, by using reflection, you can even re-call the ctor that way, but this can give unpredictable effects and you need to know quite a lot of what's going on under the hood to get it right. In the end, you probably end up having even more code then doing it the old way using "base" keyword.
  • Another approach is using an extra Init method on Base. Since you say you cannot alter Base, you'd have to create an extra class in the hierarchy that does this for you. Also a lot of work...
  • In .NET 3.5 a tempting approach is using extension methods, but they won't help because they only act on the object. Another dead-end trail...
  • A "hack" style approach is using reflection to call a private method of your Base class. This only works if your base class does the initialization using a method (doesn't matter if the init method is called from the ctor or not). If you have this private init method (you can see that with the object browser or Reflector) then I can help you calling it using reflection.
  • Two other approaches have also been suggested by William in the post before this one.
Bottom line: calling the ctor after the initialization is not possible. Calling it regardless (using reflection) may give unwanted side effects, but can be done in some cases (note that you break the intent of information hiding, an OO principle... but I'm sure you're aware of that ;-). Using any of the other approaches however should have your preference, I hope, as those stick to the "rules" of OO and C#.

-- Abel --
Avatar of keyd

ASKER

i'm aware of all these methods, but none of them is a solution. i guess the answer to my question is no. thanks
I think this Question was a good conversation on the problem put forward and should be made available to others
> i guess the answer to my question is no

this is correct, I said so in some of my posts. I second the objection of William. As you may be aware, "no" is also an answer, and quite a valuable one even though it may be not the one you hoped for.

About no-answers: https://www.experts-exchange.com/help.jsp?hi=405
About grading: https://www.experts-exchange.com/help.jsp?hi=403

However, re-reading your for-last post, I'm still puzzled with the idea. Since it is (almost) impossible to re-init a class, maybe you want something else, esp. now you say that you know all the alternatives, including reflection, already.

You ask how to do something like:

public SetBase(Base obj) {    this = obj;}

but isn't that equal to this (in the clients code):

Base obj = new Base();   // Base object initializedChild childObj = (Child) obj;   // Child object set to Base properties (same obj)

alternatively, if you want to override some behavior but not all, you can create a copy constructor, which is called like this:

Base obj = new Base();   // Base object initialized Child childObj = new Child(obj);   // new Child object set to Base properties (new obj)
-- Abel --
 
Avatar of keyd

ASKER

abel i was going to close this question awarding you points before objection from william. in know that "no" is an answer too, but i think this site is not about giving fast answers and getting the "points", but about discussions and interesting ideas.
So please lets discuss further.

Base obj = new Base();   // Base object initialized
Child childObj = new Child(obj);   // new Child object set to Base properties (new obj)

I'm interested in second line here, what can be in the copy constructor, other that assigning properties one by one.
> So please lets discuss further.

great, I totally agree. Give me a moment to elaborate, after breakfast :)
ASKER CERTIFIED SOLUTION
Avatar of abel
abel
Flag of Netherlands image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Amzing what a few eggs and some bacon can do :)

Good Solution.
Avatar of keyd

ASKER

I must say i'm a little disappointed in c# :-) But i guess this was the only possible way.
I'm sorry you are disappointed, but I think I gave you quite a lengthy answer and quite to the point. Don't show the disappointed to C# in your appreciation for me diving into details. Don't get me wrong, I love doing it, but I also love getting credits for it.

If you B-grade, there's must be something that you still miss in my answer and give me a chance to elaborate. If you B-grade because you don't like C#'s way of dealing with this, you should reconsider your grade. Remember that EE is all about a 10-points must system: https://www.experts-exchange.com/help.jsp?hi=403.

One more thing about C#. I sometimes don't like C# either, but this particular feature, about initiating an object only once, is equal among all OO languages I have worked with, including C++, Smalltalk, Eiffel, Ruby, C#, VB.NET, Java. Which is why initializable classes expose a method "Init".

-- Abel --
Avatar of keyd

ASKER

Abel, sorry for sounding like my disappointment affected your grade.
But i really think your answer is not full, this solution will not copy entire data state of object, but only public stuff. For implementing copy functionality this is not enough.

EE's 10-points must system: https://www.experts-exchange.com/help.jsp?hi=403.
says:
"If it requires you to do a little more research, or figure out one more piece of code, then it's worth a B"

Still I'll be glad to change the grade if it is possible.
Thanks for your time.
Glad I could help thanks for the ... oh never mind ;)
Thanks for the change. I asked earlier whether you wanted the reflection code, and you said you knew all that. It is very easy to amend the above code to work with private, protected, internal fields / properties / methods. If you still need that, I'd be happy to help you there, but you didn't ask, so I didn't know ;-)

-- Abel --
Avatar of keyd

ASKER

Thanks Abel, eventually i took another road with holding Base object instead of deriving it,
Although inheritance would fit nice there :-)