Why should member variables be initialized in cons

2019-02-14 07:07发布

问题:

When I first started working with object-oriented programming languages, I was taught the following rule:

When declaring a field in a class, don't initialize it yet. Do that in the constructor.

An example in C#:

public class Test
{
    private List<String> l;

    public Test()
    {
        l = new List<String>();
    }
}

But when someone recently asked me why to do that, I couldn't come up with a reason. I'm not really familiar with the internal workings of C# (or other programming languages, for that matter, as I believe this can be done in all OO languages).

So why is this done? Is it security? Properties?

回答1:

  • If you have multiple constructors, you might want to initialize a field to different values

  • When you initialize the field in the constructor, there can be no confusion over when exactly it is initialized in regard to the rest of the constructor. This may seem trivial with a single class, but not so much when you have an inheritance hierarchy with constructor code running at each level and accessing superclass fields.



回答2:

The C# compiler will take any non-static member intialization that you do inline and move it into the constructor for you. In other words this:

class Test
{
    Object o = new Object();
}

gets compiled to this:

class Test
{
    Object o;

    public Test()
    {
        this.o = new Object();
    }
}

I am not sure how compilers for other languages handle this but as far as C# is concerned it is a matter of style and you are free to do whichever you wish. Please note that static fields are handled differently: read this article for more information on that.



回答3:

One reason to do it is that it puts all of the initialization code in one place which is convenient for others reading your class. Having said this I don't really do it for two primary reasons. (1) I use TDD/Unit testing to define the behavior of my class. If you want to know what the parameterless constructor does, you should really read the tests I've built on the parameterless constructor. (2) With C# 3.0, I typically use automatic properties and inline initialization with a parameterless constructor to instantiate the object. This is much more flexible and it puts the definition of the properties right in line where the code is being used. This would override any initialization in the constructor so I rarely put any there. Of course, this only applies to C#.

Ex. (of 2)

  var foo = new Foo { Bar = "baz" };

  public class Foo
  {
       public string Bar { get; set; }

       public Foo() { }
  }


回答4:

sometimes the constructor has parameters that are used for initializing internal variables. For example size of arrays



回答5:

I haven't heard a compelling reason to not offer both options. I suspect that the real reason has to do with simplifying the language structure from a parsing perspective. This is especially true in C-derivative languages where parsing an assignment statement requires 75% of the language syntax rules. It seems to me that allowing it and defining how it would work precisely would be nice. I agree with Michael's comment about the complexity increase as you insert inheritance and multiple constructors but just because you add a feature doesn't mean that you have to use it. I would vote to support both even though my vote doesn't really add up to much.



回答6:

I always like to think of the class as a factory for objects, and the constructor as the final stop on the production line. The fields declared in the class are blueprints descirbing the object, but the blueprint won't be realised into an object before such an object is ordered tthrough a call to the constructor... Also, as someone pointed out, doing all your initialisations in your constructor will improve readability, as well as it wil provide for dynamicity in initialisation (it might not be a parameterless constructor you're dealing with).

Also, in some languages the constructor may be used for resetting an object to an original state, which is why it will then be necessary to instatiate the object in the constructor.