Lesson Goals
-
Understand the basics of Object-Oriented Programming
- Classes
- Objects
- Fields
- Properties
- Methods
- Create and Use Objects
- Learning the benefits of scope
Introduction of Objects
Object-Oriented programming is a way to structure our programs and begin the process of separating concerns based on functionality and tasks. This better helps us and others understand how a program should function, what different parts do and how we can use them.
Think of an object in the real world. Now, think about all the things it can do. Hold that thought in reserve for a moment, we'll get back to it.
Attributes of Objects
An object contains two things: State and Behavior
When we talk about objects we should talk about them in terms of their States and their Behaviors.
Let's talk about a Cat as an object in terms of the State and Behavior it has.
State of an Object
The State of an object describes it. When we think about how to describe a Cat we can say some of the following:
- Name
- Age
- Fur Color
Of course, a Cat has its own name, but we're thinking platonically right now. Don't worry, we'll get there.
What other things could we use to describe this Cat or the objects you're thinking of?
Behavior of an Object
When we talk about an object's behavior, we're talking about the actions it can perform. Talking about our Cat again, what are some things it could do?
Here are a few:
- Eat
- Meow
- Walk
- Nap
Now that we can describe our Cat and talk about some of the things it can do, let's make a Cat.
It's Alive?
Not yet but, we're working on it.
Objects need to be created. But first we need a blueprint, so let's make a Cat class. By defining a class, we are really making our own unique C# data type. Yes, classes are types! Later, we will make Cat objects that are of type Cat.
All classes use the keyword class
. We should always name classes after the object they represent. Therefore, class names are singular nouns.
class Cat
{
/// =^._.^= ∫ Um there's nothing here?
}
Shush Cat. You don't even exist yet!
Above, we are defining a class Cat
. As the technically non-existent cat said, it doesn't contain anything.
The Building-Blocks of Life
Now that we have our Cat class we'll need to add some things.
class Cat
{
private string name;
private string furColor;
private int age;
/// =^._.^= ∫ There I am?
}
Cats are so impatient.
These are the fields we made: name, furColor, and age. In most cases, they are normal variables but are very important. These fields hold data for the instance (remember that word) of the class
. In this example, we have set them to private
which means cannot be accessed from outside the class.
To access these fields, and pass them data externally, we'll need another tool.
Properties
class Cat
{
private string name;
private string furColor;
private int age;
private int lives;
public string Name
{
get {return this.name;} //returns the value
set {this.name = value;} //sets the value
}
public string FurColor
{
get {return this.furColor;}
set {this.name = value;}
}
public int Age
{
get {return this.age;}
set {this.age = value;}
}
public int Lives
{
get {return this.lives;}
set {this.lives = value;}
}
}
Our first tool is called a property
or an accessor. It allows us to get
or set
the data in those private
fields from outside the class.
Constructors
Now that we have Properties to access the fields, we still need a way to build our Cat
. We need to make a constructor:
class Cat
{
Cat(string name, string furColor, int age, int lives)
{
Name = name;
FurColor = furColor;
Age = age;
Lives = lives;
}
}
To create a Cat, an instance of our Cat class, we need a constructor. We call this a constructor because it constructs an instance of the class. Object Oriented Programming is all about creating objects (instances of a class) and communicating with those objects (calling methods). Objects don't exist until we make them. The constructor above creates an instance of our Cat
class. It uses the arguments given between the (parentheses) to initialize our fields with some starting values.
Note that the constructor has neither a return type nor a return statement-- it is only implemented to create a new object of the class. What is an object? An instance of its class. Also, the constructor name is the same as the name of its class.
Now that we understand how properties work to get and set values, we can refactor our constructor like this:
class Cat
{
public string Name { get; set; }
public string FurColor { get; set; }
public int Age { get; set; }
public int Lives { get; set; }
public Cat(string name, string furColor, int age, int lives)
{
Name = name;
FurColor = furColor;
Age = age;
Lives = lives;
}
}
Here, we've declared the Properties and made a Constructor. If you're wondering where those fields are, don't worry. They're 'behind' the properties. Everything works the same, we just made it more elegant.
Now we have our constructor in our Cat
class
.
This is a good time to talk about scope. Scope refers to accessibility from one class to other classes, and also within a class.
Classes can only see other classes in their own namespace or public classes that have been shared with the current scope with a using statement.
At the top of your class
's file are using statements. They tell your program about other class
es, which have states and behaviors of their own.
using System; //Heard of Console.WriteLine()? You're welcome.
using System.Collections.Generic;
using System.Linq;
Scope is also invoked for each pair of curly braces (opening and closing pair). Within a class, each new scope can see things from its ancestor scopes (parents, grandparents, etc), but not things defined within its descendant scopes (children, grandchildren, etc). Let's look at class level and method level scope:
namespace LearningHowScopeWorks
{
// Here we've declared a Class called Cat.
class Cat
{
// All the code that follows will be inside of these
// curly braces and is known as having "class level" scope.
// Below we've declared a method called CatMeow (the return
// type is void, meaning it returns nothing).
public void CatMeow
{
// Inside of these curly braces is the body of the method.
// Everything inside here has "method level" scope. Code
// outside of this method can't access what's inside here.
// Below we've declared and assigned a variable of type string.
// We call it a local variable because it is located inside this method.
string catHello = "Meow!"
Console.WriteLine(catHello);
}
public void MakeCatMeow
{
// Now we made a new method called MakeCatMeow. Because of method level
// scope, if we try to access the catHello variable above, inside our CatMeow method,
// we'll get an error.
Console.WriteLine(catHello);
}
}
}
Let's use our constructor to create a Cat object, and we'll also fill in some property values.
Here, we start by declaring the type of our object, which is class Cat
.
Cat cat = new Cat("Annoying", "blue", 4, 9);
Next we give it a name. Just like declaring a variable, it's written in camelCase. For simplicity we'll just call it "cat".
Cat cat = new Cat("Annoying", "blue", 4, 9);
Making use of the new
keyword, we are saying this is a new instance of this class.
Cat cat = new Cat("Annoying", "blue", 4, 9);
Finally, inside the ()
that represents our constructor, we can type information about our Cat
. It needs to be in the same order as we listed in the constructor to make sense. Even worse, if we put a string
type where an int
is expected or vice versa, we'll get a build error.
- Name: "Annoying"
- FurColor: "blue"
- Age: 4
- Lives: 9
Cat cat = new Cat("Annoying", "blue", 4, 9);
Here's our Cat
. Using dot notation, we can call the instance name (cat) and the .
operator (dot operator) followed by a class property to access our property values. So if we call "cat.Name", we can access the name value from our Cat object.
class Program
{
static void Main(string[] args)
{
Cat cat = new Cat("Annoying", "blue", 4, 9);
Console.WriteLine("My name is " + cat.Name + " !");
}
}
Console output:
My name is Annoying!
Now our Cat has state but no behavior. To act upon or give our Cat object behavior, we'll have to write some methods!