Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

One Constructor for a Class and its Nested Classes

For the sake of this example, suppose we're making a dumbed-down game of Clue™. We have a class for each Room in the mansion, and subclasses for the Suspect and Weapon in each Room. Something like:

class Room
{
  public string Name;
  public int Width;
  public int Height;
  // and so on...

  public class Suspect
  {
    public string Name;
    public bool isPurple;
  }

  public class Weapon
  {
    public string Name;
    public bool IsMetal;
  }
}

Before adding the Suspect and Weapon classes, the Room constructor looked something like:

public Room(string Name, int Width, int Height)
{
  this.Name = Name;
  this.Width = Width;
  this.Height = Height;
}

Initializing a room used to be as simple as: Room[i] = new Room("Conservatory", 7, 3); - but after the nested classes were introduced, can their initialization be handled through a shared constructor with the main class? Something like:

Room[i] = new Room("Library", 8, 5, "Professor Plum", true, "Candlestick", true);

I can't seem to find any examples of a similar setup. How can I accomplish this?

like image 749
4444 Avatar asked Jul 13 '12 15:07

4444


People also ask

Can nested class have constructor?

3.2. They cannot have access modifiers in their declaration. They have access to both static and non-static members in the enclosing context. They can only define instance members. They're the only type of nested classes that cannot define constructors or extend/implement other classes or interfaces.

What is nested class with example?

A nested class is a member and as such has the same access rights as any other member. The members of an enclosing class have no special access to members of a nested class; the usual access rules shall be obeyed. For example, program 1 compiles without any error and program 2 fails in compilation.


3 Answers

Instead of having your constructor have so many parameters, why not do something like this?

public class Room
{
    public Room(Suspect suspect, Weapon weapon)
    {
        SuspectInRoom = suspect;
        WeaponInRoom = weapon;
    }

    public Suspect SuspectInRoom { get; set; }
    public Weapon WeaponInRoom { get; set; }
}

// Example usage:

Suspect coronelCustard = new Suspect("Coronel Custard");
Weapon musket = new Weapon("Musket");

Room someRoom = new Room(coronelCustard, musket);

// Then your room can be used to access all sorts of data.

Console.WriteLine(someRoom.SuspectInRoom.Nickname); // "The Big Kahuna"
Console.WriteLine(someRoom.WeaponInRoom.AttackDamage); // "20"

When nested classes are introduced to a main class, can their initialization be handled through a shared constructor with the main class? Eventually I'd hope to initialize all three classes in the same line...

If your nested class has a public constructor you can do that.

Example:

Room someRoom = new Room(new Suspect("Colonel Custard"), new Weapon("Musket"));

But, it's kind of a code smell to do things this way. It's better to use already created and instantiated members in constructor calls. It's a personal choice either way.

like image 105
Only Bolivian Here Avatar answered Sep 28 '22 07:09

Only Bolivian Here


You don't even need constructores... just use the initializers:

   var room = new Room { Name = "Library",
                         Width = 7,
                         Height = 3,
                         Suspect = new Suspect { Name = "Professor Plum",
                                                 PlaysCroquet = false },
                         Weapon = new Weapon { Name = "Candlestick",
                                               IsShiny = true }
                        };
like image 45
Jaime Torres Avatar answered Sep 28 '22 07:09

Jaime Torres


A simple way to do this is to give the Suspect and Weapon classes public constructors, so they can be instantiated outside of the Room class (I assume this is acceptable, since the classes are declared public).

The Room constructor can then take references to a Suspect and a Weapon. This gives you the flexibility to create Suspect and Weapon objects at some prior point, and pass them into a Room on construction - it also prevents the Room class constructor from having to know about the Suspect and Weapon classes' properties (and requiring modification when you add to them).

For brevity, you can still construct all the objects in a single line, like so:

Room[i] = new Room("Library", 8, 5, new Suspect("Professor Plum", false), new Weapon("Candlestick", true));
like image 36
Dan J Avatar answered Sep 28 '22 07:09

Dan J