Lesson Objectives
At the end of this lesson, you will know…
- How a child (derived) class calls the constructor of its base class
Let’s clean up the code a little
Adding a constructor to a base class is a little more involved than adding one to a class that doesn’t have any derived (child) classes.
When you create an object from a derived class, it uses the constructor for both that class and its base class. So, if you add a custom constructor to your base class, you need to have a way for the derived class to pass values to it.
If you think about this, it makes sense why this needs to be done. With a custom constructor, you are saying, “I need these values before I can create this object.” When you create an object from a derived class, the base class still needs to have those values. So, you have to pass them to the derived class’ constructor, which passes them on to the base class’ constructor.
Here’s how you do that.
Step 1: Start Visual Studio Express 2013 for Desktop, and open the solution.
Step 2: Double-click on the Item class, in the Engine project, to start editing it. After the properties, add these lines, to make your constructor:
public Item(int id, string name, string namePlural) { ID = id; Name = name; NamePlural = namePlural; }
NOTE: If you try to build the solution right now, you’ll see there are errors with the HealingPotion and Weapon classes. These are the classes that are derived from the Item class, and [right now] they don’t have any values to pass to the Item class’ new constructor.
Step 3: Open the HealingPotion class, and add these lines to make its new constructor:
public HealingPotion(int id, string name, string namePlural, int amountToHeal) : base(id, name, namePlural) { AmountToHeal = amountToHeal; }
Notice that the HealingPotion constructor has parameters for the one property it has (AmountToHeal) and the three properties it uses from the base class (ID, Name, and NamePlural).
Inside the constructor, it sets the AmountToHeal property to the value that was passed through the amountToHeal parameter.
Also notice that after the constructor has a list of its parameters, it has this piece of code:
: base(id, name, namePlural)
What that does is take the values from the parameters in the HealingPotion constructor (id, name, and namePlural) and passes them on to the constructor of the Item class. This is how we get parameters into the base class, when instantiating a derived class.
Step 4: Edit the Weapon class, by adding this constructor code:
public Weapon(int id, string name, string namePlural, int minimumDamage, int maximumDamage) : base(id, name, namePlural) { MinimumDamage = minimumDamage; MaximumDamage = maximumDamage; }
After you add this, you can try rebuilding the solution. Now, since the derived classes are passing the required values to the base class, it will build without any errors.
Step 5: Edit the LivingCreature class. Add this constructor code:
public LivingCreature(int currentHitPoints, int maximumHitPoints) { CurrentHitPoints = currentHitPoints; MaximumHitPoints = maximumHitPoints; }
Again, if you try to build the solution now, you’ll get an error that the Monster and Player classes (the classes that derive from LivingCreature) have a problem.
Step 6: Edit the Monster class, by inserting this constructor:
public Monster(int id, string name, int maximumDamage, int rewardExperiencePoints, int rewardGold, int currentHitPoints, int maximumHitPoints) : base(currentHitPoints, maximumHitPoints) { ID = id; Name = name; MaximumDamage = maximumDamage; RewardExperiencePoints = rewardExperiencePoints; RewardGold = rewardGold; }
Step 7: Insert this constructor code into the Player class:
public Player(int currentHitPoints, int maximumHitPoints, int gold, int experiencePoints, int level) : base(currentHitPoints, maximumHitPoints) { Gold = gold; ExperiencePoints = experiencePoints; Level = level; }
Now, if we try building the solution, we get an error. That’s because in the SuperAdventure UI code, we are instantiating a Player object without any parameters. Now that we have a custom constructor in the Player class, we need to use that and pass in the appropriate parameters.
Step 8: Right-click on SuperAdventure.cs, in the SuperAdventure project, then select “View Code”. Change line 23 to this:
_player = new Player(10, 10, 20, 0, 1);
Now that we are passing all the values in the constructor, to set the player object’s properties, we can delete lines 25 through 29, where we were setting the properties individually.
You could leave lines 25 through 29. They’ll still work, and they won’t hurt anything. But you’re already setting the properties to those values, so you might as well remove them and make your code a little cleaner.
Summary
You’ll probably need to use some amount of inheritance in any decent-sized program. And now you know how to make a custom constructor work in classes that use inheritance.
This may be overkill for the simple game that we’re building. However, you’re going to need to know how inheritance works if you program in C#, or another object-oriented programming language. Hopefully, with small, simple classes like these, it’s easy to understand.
Source code for this lesson
Next Lesson: Lesson 09.1 – Using your classes as datatypes
Previous lesson: Lesson 08.1 – Setting properties with a class constructor
All lessons: Learn C# by Building a Simple RPG Index
Why you didnt pass currentHitPoints and maximumHitPoints vars to Monster’s base class from Monster’s consructor?
In Step 6, at the end of the parameter list, the code “: base(currentHitPoints, maximumHitPoints)” passes the values for currentHitPoint and maximumHitPoint (from the Monster parameters) to the base class constructor parameters.
It’s missing from the walkthrough though. This step stumped me as well until I checked your source files. In the walkthrough you have
public Monster(int id, string name, int maximumDamage, int rewardExperiencePoints, int rewardGold, int currentHitPoints, int maximumHitPoints)
But in the source files you have
public Monster(int id, string name, int maximumDamage, int rewardExperiencePoints, int rewardGold, int currentHitPoints, int maximumHitPoints) : base(currentHitPoints, maximumHitPoints)
I believe that’s in Step 6 of the lesson here, unless there is a different problem that I’m not seeing.
Note: First line in Monster is
public Monster(int id, string name, int maximumDamage, int rewardXP, int rewardGold, int currentHitPoints, int maximumHitPoints):base(currentHitPoints, maximumHitPoints)
Ah, it is there. I was also a little stumped at first.
It was not obvious initially, but in the example code for Step 6 there is a scroll bar that you can use to scroll to the right to see the rest of the code.
Yes, there’s a plug-in I use to format and display the source code. It’s the best one I’ve found, but it still has a couple bits of odd behavior. 🙁
“I’m getting an ‘object’ does not contain a constructor that takes 2 arguments” on line 20 of Monster.cs?
Hi Brodie,
I’m sorry I wasn’t able to answer earlier. I didn’t have Internet in my new apartment until last night.
The plug-in that shows the code samples on the site works a little strangely, so you might not be able to see all the changes that needed to be made. I think the problem may be in the Monster class. Check it against the code on GitHub here https://gist.github.com/ScottLilly/b460c4adbe1abde3c7f4. If that doesn’t fix the problem, plese let me know. I should have some time to look into it a bit more this weekend.
When inserting the constructor into Monster.cs, I get this error: “CS0029 Cannot implicitly convert ‘string’ to ‘int’ on line 20” (line 20 is “Name = name”). Help?
Hi Leo,
Can you double-check these three things?
1. Make sure that you have the LivingCreature class as a base class for Monster:
Line 9 (Monster.cs):
public class Monster : LivingCreature
2. That you have the Monster constructor calling the base constructor correctly (especially with the parameters in the correct order):
Line 17 (Monster.cs):
public Monster(int id, string name, int maximumDamage, int rewardExperiencePoints, int rewardGold, int currentHitPoints, int maximumHitPoints) : base(currentHitPoints, maximumHitPoints)
3. That the parameters are in the correct order, and have the correct datatypes, in the LivingCreature class:
Line 14 (LivingCreature.cs):
public LivingCreature(int currentHitPoints, int maximumHitPoints)
Let me know if those are all correct and I can help you investigate further.
why did you put _player =new Player(); instead of Player _player=new Player();
You only include the datatype (“Player”) when you declare the variable – basically telling the compiler “We’re going to have a variable named ‘_player’. It’s going to hold a Player object. So set aside some space for it”.
We’ve already done the declaration higher up with the line “private Player _player;” When we declared the _player variable, it was at the class level (inside the curly braces for the class, but outside all the methods of the class). So, _player is visible anywhere inside the class. When we do “_player = new Player();”, we’re only filling the already-declared variable with the object.
If you want to, you could add in “Player” to that line. You should see an error that says the _player variable has already been declared.
Why don’t you just make constructors in classes for everything? For example:
public class Location1 : Location
{
public Location1()
{
id = 1; name = “Home”; description = “This is your home”;
}
}
Hello Sanek,
In your sample, Location1 would be a child class of Location. We normally only create child classes when we want to add more details for a smaller set of the base class. For example, if we wanted a MountainLocation class that would also include a Height property. For the Location class, we don’t need that, because we are only going to create multiple Location objects.
This might be clearer after lessons 09.1, 10.1, and 11.1. Those are where we start to populate our “World” with the different locations. If those lessons do not make it clear, please let me know.
Hi there,
First of all I want to say that this series has been a big help for me and I realize that this article is old and is designed for beginners, but one thing has me stumped. Is it an acceptable coding standard to create class constructors that are so large?
The monster class’s constructor is huge and has well over 5 parameters. I could’ve sworn that I read somewhere that a class constructor should usually contain no more than 4 parameters at the most, otherwise it’s likely you can extract a further class out of it. Is this an incorrect statement or have you simply made these constructors to ease the simplicity of the lessons
I’m still fairly new to programming in general and creating a clean, refactored, project standard style of source code is something I find myself worrying about constantly so please excuse me if my comment is confusing or incorrect I’m just merely confused and curios as to what a good coding practice would be when it comes to constructors.
Hi James,
You are correct. It’s generally best if your constructor has fewer parameters. Actually, you could say that is true for all functions. However, for the Monster class, I don’t see a great way to group any of the parameters into a their own class. We could potentially group rewardExperiencePoints + rewardGold into a Reward class, and currentHitPoints + maximumHitPoints into a HitPoints class. But that would only eliminate one parameter per object, and require us to add a little complexity by needing to instantiate, and populate, the two new classes, to pass into the Monster class constructor.
This would definitely make sense if we were writing a Customer class, and wanted to capture their personal information, including a billing address and shipping address. Instead of passing in individual parameters for BillingStreetAddress, BillingCity, BillingStateProvince, BillingPostalCode, ShippingStreetAddress, ShippingCity, ShippingStateProvince, ShippingPostalCode, etc., it would make sense to create an Address class. Then, we would instantiate an Address object for the billing address, another one for the shipping address, and pass those objects in the Customer class constructor.
This is one of those situations where you need to look at your options and decide which seems best to you.
Hello Scott,
This is a great lesson in a great series! One question related to this lesson though.
I am creating a game where things like Creature, Player, Location etc. are abstract classes, and then specific creatures like Pig, or specific Player Professions and Location Types etc. are child classes of that abstract class.
I believe that in one of the earlier lessons you mentioned (which I also remember from some other course) that you cannot create an instance of something that belongs to an abstract class. Thus I set up everything so that only derived classes have constructors. In fact, when I try to create a constructor for an abstract class, I receive an error in the editor.
Am I right in saying that abstract classes cannot have constructors on their own (which would be logical, since they cannot be instantiated), or is that incorrect?
Thanks in advance for your reply and have a great day!
Mike
Thanks Mike!
You could make a protected (non-abstract) constructor in the abstract class, and call it from within the derived classes. It’s not extremely common, but it can be done. And, you still wouldn’t be able to instantiate the abstract class, only the derived classes. Here’s some more information on how to do that: http://stackoverflow.com/questions/2299037/abstract-constructor-in-c-sharp.
Just wanted to say it is such a good tutorial to get started with c#. Thank you for putting so much effort in it with a step by step guide! It isn’t to complex so far, which i really like.
I hope I finish the whole tutorial.
Regards from Berlin_GER
Thank you. I’m glad you like it.
Hi, when i open visual studio 2015 and open project nothing is opening! Can you help? I can click start button and it opens my game but none of the code is opening. Thanks, Danny
If you want to view or edit one of your class files, you can double-click on the file in the Solution Explorer part of Visual Studio (the upper-right section, where all the projects and classes are).
Please tell me if that doesn’t solve the problem.
public Monster(int id, string name, int maximumDamage, int rewardExperiencePoints, int rewardGold, int currentHitPoints,
int maximumHitPoints) : base(currentHitPoints, maximumHitPoints)
{
ID = id;
Name = name;
MaximumDamage = maximumDamage;
RewardExperiencePoints = rewardExperiencePoints;
RewardGold = rewardGold;
}
Name = name; is coming up with error CS0029 (cannot implicitly convert type ‘string’ to ‘int’) i have followed the lessons and cannot figure it out, can anyone tell me what i’m doing wrong?
Hi Jacob,
The error message is saying that the existing code is trying to assign a string value to an integer property (or variable). That’s the “cannot implicitly convert type ‘string’ to ‘int'” part of the error message. It’s also telling you that this is happening with the “Name” property.
So, check the datatype of the “Name” property. I’m guessing it is set to “int”, when it needs to be “string”.
Please tell me if that is not the source of the error.
That fixed it, thank you.
Also thanks for creating this tutorial!
You’re welcome!
Scott Lilly thank you so much for creating this series. I’ve been doing code tutorials for a year and never could grasp a lot of the concepts. The way you relate this to a game makes it a lot easier to understand and not as boring. Appreciate it!
You’re welcome. When I personally try to learn something, it always seems easier if there is a final project – and not just a lot of small, unconnected things.
‘object’ does not contain a constructor that takes 2 arguments
this appeared when i entered : base(currentHitPoints, maximumHitPoints)
for monster.cs
On line 9 of the Monster class, do you have this, so it knows to inherit from the LivingCreature class?
public class Monster : LivingCreature
If that doesn’t fix the problem, can you upload your solution (including the directories under it, and all the files in those directories) to GitHub or Dropbox, so I can look at it?
For Player, when I try to update the hit points, nothing changes. It just stays at zero.
The gold, experience and level all changes to their different values, but hit points stays at zero. What can I do to fix this?
Can you upload your solution (including the directories under it, and all the files in those directories) to GitHub or Dropbox, so I can look at it?
LINK REMOVED FOR PRIVACY
The solution is just the .sln file, right? I’m new to Vs.
I need all the files in that directory and its sub-directories (the .cs files, the xaml.cs files, the app.config, the PlayerData.xml files, etc.). It is probably easiest to compress the directory where you solution is (including its sub-directories) into a .zip file and upload that to Dropbox.
Ok, I zipped my entire project folder, so I should have all the files you needed.
LINK REMOVED FOR PRIVACY
There are two changes to make, to fix the problem.
First, in the Player class, remove the “CurrentHitpoints” property. You shouldn’t need it, since the program needs to use the property from the base class (LivingCreature).
Second, change line 25 of SuperAdventure,cs to the line below. This will make the program use the “CurrentHitPoints” property from LivingCreature class. Notice that the “P” was upper-case in LivingCreature, but lower-case “p” when it was in Player. That’s something to watch out for, since C# treats those as two different properties.
lblHitPoints.Text = _player.CurrentHitPoints.ToString();
Let me know if that doesn’t fix the problem, or if you have any other questions.
Thanks, that fixed it.
I really need to learn to pay more attention. I was stuck for days on a problem that was fixable in under a minute.
You’re welcome.
As you write more programs, you’ll become faster at solving errors. You’ll start to build a mental library of problems, what usually causes them, and how to fix them. Then, people will think you’re a programming wizard. 🙂
Great tutorial.
Small note – step 8 should say to change the Player constructor on line 28 (not line 23 – location code is lines 23-26 when I follow through the guide) and delete the lines 30 – 34. Just in case it confuses anyone 🙂
Anyway, excellently clear guide so far. Thank you.
Thanks Glenn,
I think Visual Studio recently changed the default “using” lines at the beginning of the class (when it creates a new class). I’ve seen that from some other people. You might need to watch out for that in future lessons.
Hi Scott.
Great tut. It is really fun to go through for somebody like me who is starting from scratch right here.
I have a quick question though.
In step 3, after the first part of the constructor, we are inheriting from “base”.
“HealingPotion” inherits from “Item”, so am I correct in assuming “base” is just referencing “Item” since it is the base class? Or am I meant to have created a class called “base”?
And a follow up to that, if “base” is just referencing “Item”, why don’t we just inherit from “Item” again?
Lastly, this just confused me while going through this so I apologize for so many questions, why do we have to re-inherit? “HealinPotion” already inherits from “Item” and “Item” already has the “id”, “name” and “nameplural” properties.
Thanks for any help on this.
Hi Kebers,
I’m sorry it’s taken so long to respond.
Yes, the “base” in the constructor means the base class, which is the “Item” class (which was defined by saying “public class HealingPotion : Item”). When a child class constructor passes values to its parent class, you always do that by adding ” : base()” after the constructor. The compiler is smart enough to know “base” means “Item”, because we already declared HealingPotion’s parent as Item.
For your last question, are you talking about passing the parameters into the HealingPotion constructor, but only using “amountToHeal” in the HealingPotion class – while passing the other parameters to the “base” (Item) constructor? If so, maybe think of this like this:
Your neighbor asks you for a favor. He can’t go to the store, but needs some ingredients to cook dinner. He gives you a list of the things he needs (these equate to the parameters of the parent class). Your neighbor’s son (equating to the child class) is going to help you carry the items back, but he’ll only do that if you buy him a candy bar (the one “parameter” he cares about in his constructor. You and the son go to the grocery store, and you buy everything on your neighbor’s shopping list, plus a candy bar for the son. The son takes his candy and eats it – stores that parameter in his (the child class’) property. Then, he takes all the other items to his parent – the parameters needed by the parent class.
That’s stretching the metaphor a bit, so let me know if it still isn’t clear.