• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1173
  • Last Modified:

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.
0
keyd
Asked:
keyd
  • 11
  • 8
  • 4
1 Solution
 
abelCommented:
You can do that like so:



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

Open in new window

0
 
abelCommented:
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

0
 
keydAuthor Commented:
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
    }
}
0
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 
abelCommented:
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).
0
 
abelCommented:
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).
0
 
keydAuthor Commented:
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...
}
0
 
abelCommented:
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
}
0
 
keydAuthor Commented:
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.
0
 
williamcampbellCommented:
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

0
 
abelCommented:
> 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 --
0
 
keydAuthor Commented:
i'm aware of all these methods, but none of them is a solution. i guess the answer to my question is no. thanks
0
 
williamcampbellCommented:
I think this Question was a good conversation on the problem put forward and should be made available to others
0
 
abelCommented:
> 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: http://www.experts-exchange.com/help.jsp?hi=405
About grading: http://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 --
 
0
 
keydAuthor Commented:
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.
0
 
abelCommented:
> So please lets discuss further.

great, I totally agree. Give me a moment to elaborate, after breakfast :)
0
 
abelCommented:
after a long breakfast in the sun... ;)

Here: http://msdn.microsoft.com/en-us/library/ms173116(VS.80).aspx, Microsoft shows an example of how they think a copy constructor should look like. This is the traditional approach and I can't remember having seen languages (not even Eiffel, Sather or Oberon) that deal with that differently. Looser languages like Python, Ruby and Perl-OO have easier ways of doing this.

However, there are other ways to deal with that. I'm sure you have a utility class somewhere, if not, just make the following a static method. You can use it to copy any public fields or properties to the other object. Make sure the Source object is the parent (Base). Maybe this is not the ideal method, but at least it does the job for you.

Note that the copy constructor in the example takes a Base object. That makes it easier in terms of castability. Depending on your situation, you may want to amend it a bit. I assumed .NET 3.5 here (using shortcut properties). Call the code as follows:

    Base myBaseObj =  new Base();
    myBaseObj.prop3 = "this is property 3";

    Child myChildObj = new Child(myBaseObj);
    Debug.WriteLine("prop 3: " + myChildObj.prop3);

In the example below I included a copy constructor "traditional style" for the Base class. If you have it, you can use it, if you don't have it, ignore it. The Clone method is the imported part here.

-- Abel --

PS: I first build the method myself and then changed it slightly to match this method I found online: http://www.codeproject.com/KB/dotnet/clone_object_csharp.aspx. There are other ways of cloning, like this one: http://www.codeproject.com/KB/cs/cloneimpl_class.aspx, but I consider the first to be the easiest to implement.

public static class Util
{
    public static void CloneObject(object Source, object Destination)
    {
        // exceptions
        if (Source == null)
            throw new ArgumentNullException("Source");
        if (Destination == null)
            throw new ArgumentNullException("Destination");
 
        // copy each value over
        foreach (PropertyInfo pi in Source.GetType().GetProperties())
            if (pi.CanRead && pi.CanWrite)
                pi.SetValue(Destination, pi.GetValue(Source, null), null);
 
    }
}
 
public class Base
{
    public string prop1 { get; set; }
    public string prop2 { get; set; }
    public string prop3 { get; set; }
    public Base()
    {
        prop1 = "initialized prop1";
        prop2 = "initialized prop2";
    }
    public Base(Base obj)
    {
        // Microsoft's way of a copy constructor
        this.prop1 = obj.prop1;
        this.prop2 = obj.prop2;
    }
}
 
public class Child : Base
{
    public Child() { }
    public Child(Base obj)
        : base(obj)          // calling base(obj) if the base has a copy ctor
    {
        // simpler then Microsoft's method
        Util.CloneObject(obj, this);
    }
}

Open in new window

0
 
williamcampbellCommented:
Amzing what a few eggs and some bacon can do :)

Good Solution.
0
 
keydAuthor Commented:
I must say i'm a little disappointed in c# :-) But i guess this was the only possible way.
0
 
abelCommented:
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: http://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 --
0
 
keydAuthor Commented:
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: http://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.
0
 
williamcampbellCommented:
Glad I could help thanks for the ... oh never mind ;)
0
 
abelCommented:
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 --
0
 
keydAuthor Commented:
Thanks Abel, eventually i took another road with holding Base object instead of deriving it,
Although inheritance would fit nice there :-)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 11
  • 8
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now