Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple constructors with one parameter

Tags:

c#

So, at school we got an assignment to make a car in OOP, until now its been pretty easy and straight forward. But now I need to create four constructors, one with no parameters, two with one parameter and one with two parameters.

As far as I know the way overloading works is that it checks the amount of parameters you supply it with and then checks which constuctor it has to use. As two of the constructors are the same, both accepts ints, only one needs to change the amount or gears, and the other needs to change the maximum speed.

Is there a way to do this without passing an extra parameter?

like image 875
Gideon Avatar asked Mar 02 '12 21:03

Gideon


3 Answers

As far as I know the way overloading works is that it checks the amount of parameters you supply it with and then checks which constuctor it has to use.

No, overloading isn't based solely on the number of parameters - it's based on their types too.

However:

As two of the constructors are the same, both accepts strings

That's a problem. You can't declare two constructors like this:

public Foo(string x)
{
}

public Foo(string y)
{
}

Those signatures clash as far as overloading is concerned.

I would suggest having public static factory methods, so you can specify what you're trying to create:

public static Foo FromGears(string gears)
{
    return new Foo(...);
}

public static Foo FromMaximumSpeed(string maxSpeed)
{
    return new Foo(...);
}

You'd then possibly have one constructor which accepted both values, and default whichever one's missing when you call the constructor from the factory method.

However, there are two other oddities in your description:

  • You're using strings for two values which sound like they should be numbers (or possibly one number, and one number-and-unit)
  • You're talking about declaring constructors, but then using the word "change" as if they're going to change an existing instance. That doesn't make sense - constructors are used to create new objects.

EDIT: Okay, now we know a bit more, here's the sort of thing I mean:

public class Car
{
    private const int DefaultGears = 5;
    private const int DefaultTopSpeed = 180;

    private readonly int gears;
    private readonly int topSpeed;

    public Car(int gears, int topSpeed)
    {
        this.gears = gears;
        this.topSpeed = topSpeed;
    }

    public static Car CreateWithGears(int gears)
    {
        return new Car(gears, DefaultTopSpeed);
    }

    public static Car CreateWithTopSpeed(int topSpeed)
    {
        return new Car(topSpeed, DefaultGears);
    }
}

Note that you could use optional parameters and named arguments for this too in C# 4:

public class Car
{
    public const int DefaultGears = 5;
    public const int DefaultTopSpeed = 180;

    private readonly int gears;
    private readonly int topSpeed;

    public Car(int gears = DefaultGears, int topSpeed = DefaultTopSpeed)
    {
        this.gears = gears;
        this.topSpeed = topSpeed;
    }
}

Then:

Car car = new Car(gears: 4);
Car car = new Car(topSpeed: 30);

I wouldn't recommend that in general though - certainly not while you're still relatively new to the language. There are various subtleties around optional parameters.

like image 120
Jon Skeet Avatar answered Oct 24 '22 07:10

Jon Skeet


Overloaded methods (and constructors) must differ in their signature. This means that they must have a different number of parameters or parameters having a different type (or both). The names of the parameters are not taken into account. This means that you cannot have two constructors both having one string parameter.

Constructors are not made to change anything but to initialize an object. If you want to change a value, consider adding a method like ChangeGears(string gears).

like image 27
Olivier Jacot-Descombes Avatar answered Oct 24 '22 09:10

Olivier Jacot-Descombes


In short no. Constructors not only depend on the number of parameters but on their types as well.

public Car(string gears)
{

}

public Car(string maxSpeed)
{

}

You can't call that, because they are essentially the same constructor, think about it, when you pass in a string, it is a value that you are passing, so the compiler has no idea what constructor to use: if you wanted to set number of gears to 6 or max speed to 6 the call would still be new Car("6"), kind of ambiguous wouldn't you say?

The homework spec can't say to have two constructors which take strings, since this is impossible. Really the only sane way to accomplish this would be to use static factory methods or as you said to introduce another parameter.

Looking at what you have commented on in other answers leads me to believe something like this might work for you, however it is hard to know exactly what your homework wants.

public Car()
{
    ... // Do your setting of your default values here (# of gears, max speed)
}

public Car(int n)
{
    if( n > 10 ) 
    {
        // Use n to set your max speed
    } else {
        // Use n to set your # of gears
    }
}

It seems unlikely that a car will possess more than 10 gears, or that its maximum speed will be less than 10, so in this way you can use a single constructor for setting both your # of gears and top speed. (Keep in mind from what you've asked that this probably won't answer your homework, but it would be a sufficient way IMO to use a constructor that can set max speed and number of gears without adding another parameter, assuming that you have some sort of guarantee that the cars max speed is >=10 and the number of gears is < 10)

like image 27
NominSim Avatar answered Oct 24 '22 09:10

NominSim