Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass this to base constructor

I am trying to implement good design patterns for a program I am writing. I have a class structure like this.

abstract class SomeBase
{
     public SomeObject obj { get; protected set; } 

     protected SomeBase(SomeObject x)
     {
           obj = x;
     }

     //Other methods and fields...
}

public class SomeDerived : SomeBase
{

     public SomeDerived() : base(new SomeObject(this))
     {

     }

}

Now as I'm sure you know, you can't pass this in a base constructor, because the object hasn't been initialized at this point in time. Anyhow I was really hoping there was a workaround. It's not best practice for me to allow SomeDerived() to handle the setting of a base classes field. I would like to pass this new object up the chain.

like image 931
guitar80 Avatar asked Sep 18 '14 17:09

guitar80


People also ask

Can we pass parameter to base class constructor?

Any parameters to the constructor can be used as parameters to base , or as part of an expression.

Can we pass parameters to base?

To pass in parameter values, simply append them to the query string at the end of the base URL.

What parameters need to be passed to a constructor?

This method has four parameters: the loan amount, the interest rate, the future value and the number of periods. The first three are double-precision floating point numbers, and the fourth is an integer.

What helps to call the base constructor?

You can call the base class constructor from the child class by using the super() which will execute the constructor of the base class. Example: Javascript.


2 Answers

This is not possible, use an Init method after the constructor:

 abstract class SomeBase
 {
      private SomeObject _obj { get; set; } 
      public SomeObject obj 
      {
           get 
           {    // check _obj is inited:
                if (_obj == null) throw new <exception of your choice> ;
                return _obj;
           } 
      }

      protected SomeBase()
      {
           obj = null;
      }

      protected void Init()
      {
           obj = x;
      }

      //Other methods and fields...
 }

 public class SomeDerived : SomeBase
 {

      public SomeDerived() : base()
      {
           Init(new SomeObject(this));
      }

 }
like image 101
Peter Krassoi Avatar answered Oct 02 '22 14:10

Peter Krassoi


Well, you actually have it in the base constructor, so there is no need to pass it.

using System;

abstract class SomeBase
{
    public SomeObject obj { get; protected set; }

    protected SomeBase()
    {
        // Will be executed as 1st step
        Console.WriteLine(1);

        // "this" here is SomeDerived object
        obj = new SomeObject((SomeDerived)this);
        // If you don`t like to depend upon SomeDerived type here,
        // you can do the same using the following line:
        //obj = (SomeObject)Activator.CreateInstance(typeof(SomeObject), this);
    }
}

class SomeObject
{
    public SomeObject(SomeDerived obj)
    {
        if (obj.obj == null)
        {
            // Will be executed as 2nd step
            Console.WriteLine(2);

            // You have the reference to SomeDerived here
            // But its properties are not yet initialized
            // (both SomeDerived and SomeBase constructors are in the progress)
            // So you should not access these properties 
            // in the SomeObject class constructor,
            // but you can do it in any method of SomeObject class 
            // (at the time the method will be called all constructors are finished).
        }
    }
}

class SomeDerived : SomeBase
{
    public SomeDerived()
    {
        // Will be executed as 3rd step
        Console.WriteLine(3);

        if (this.obj != null)
        {
            // You have the reference to SomeObject here,
            // which itself already got an access to SomeDerived reference
        }
    }
}

class MainClass 
{
    public static void Main (string[] args) 
    {
        var instance = new SomeDerived();
        Console.WriteLine (instance.obj); // Outputs SomeObject
    }
}

https://repl.it/@Konard/LinenZealousBlockchain

Another solution will be to use the lambda expression, so the SomeDerived class will have total control on how the reference to it will be passed into SomeObject.

using System;

abstract class SomeBase
{
    public SomeObject obj { get; protected set; }

    protected SomeBase(Func<SomeBase, SomeObject> someObjectInitilizer)
    {
        // Will be executed as 1st step
        Console.WriteLine(1);

        // "this" here is SomeDerived object
        obj = someObjectInitilizer(this);
    }
}

class SomeObject
{
    public SomeObject(SomeDerived obj)
    {
        if (obj.obj == null)
        {
            // Will be executed as 2nd step
            Console.WriteLine(2);

            // You have the reference to SomeDerived here
            // But its properties are not yet initialized
            // (both SomeDerived and SomeBase constructors are in the progress)
            // So you should not access these properties 
            // in the SomeObject class constructor,
            // but you can do it in any method of SomeObject class 
            // (at the time the method will be called all constructors are finished).
        }
    }
}

class SomeDerived : SomeBase
{
    public SomeDerived() : base((@this) => new SomeObject((SomeDerived)@this))
    {
        // Will be executed as 3rd step
        Console.WriteLine(3);

        if (this.obj != null)
        {
            // You have the reference to SomeObject here,
            // which itself already got an access to SomeDerived reference
        }
    }
}

class MainClass 
{
    public static void Main (string[] args) 
    {
        var instance = new SomeDerived();
        Console.WriteLine (instance.obj); // Outputs SomeObject
    }
}

https://repl.it/@Konard/ParchedYellowgreenType

like image 33
Konard Avatar answered Oct 02 '22 13:10

Konard