I have been teaching myself C# for awhile now and I have come a long way, but one part I am getting tripped up on is when I instantiate something. At the basic level I am totally fine but it’s when I start instantiating objects from other classes I start to get confused and my mind eventually turns to mush and I don’t understand what is what.
An example would be:
Car car = new Car();
I get that I am creating an object from the Car class. But then I will see code something like this:
Car car = new Truck(); or Truck car = new Car();
Not sure what side does what, if that makes any sense. Like the left side is the class your calling it from? and then the right is the object you are creating? I just get so confused when I start creating multiple classes. I haven’t really found something that lays out each part. Can someone explain this to me in a very basic way? And know a good way of remembering and keeping it straight in my mind when I have a lot going on in my code?
Thanks for the help!
I think you’re asking how it can be true that the variable is of type Car
but I’m assigning it a new Truck
object? The answer is an OOP feature called inheritance.
For this to work, I’d have to have my classes defined like this:
The magic is that : Car
on the end of the Truck
‘s declaration. That tells C# “This class is named Truck, and it is derived from the class Car.” I won’t go into too many details because there are a lot of inheritance tutorials, but a good simple way to put it is when I declare the classes this way, “a Truck
is a Car
“. In this case we call Car
a “base class” and Truck
a “derived class”.
So since a Truck
is a Car
, I can use a Truck
anywhere I’m expecting a Car
. That’s what’s happening on this line:
On the left side, we see car
is a variable of type Car
. On the right side, we’re trying to assign a new Truck
to that variable. C# allows that, because a Truck
is a Car
.
Generally we don’t write assignment statements like this. Instead we might see something like this:
This is a method that rents “a car”. You might get a truck, a van, or a bus. You don’t care if you call this method, you just need four wheels and a motor. That way you can use it with something like:
That’s a method that drives to work, and it needs a car to do so. So our snippet to use these might look like:
It’s possible we rent a Truck
. That’s what is nice about inheritance: because we said it is a Car
, we can use it like a Car
without caring. That’s the value of the feature. It’s hard to use it right, but when you do you can make very flexible systems that can be extended without rewriting a lot of code!
Wow that’s awesome!
I think you are right, I think I saw the difference from type to constructor when I was watching an inheritance tutorial. It probably something like this:
I was getting so confused when implementing this on my own. I guess I just need to practice to get it cemented in my head.
Thanks!
Without a doubt one of the nicest intro to inheritance I’ve ever read. I salute you!
Car car = new Car();
You are creating a new object from the Car class called car.
Truck car = new Car();
You are creating a new object from the Truck class called car. That is backwards and not a good example as youd need a Truck class to do this. Car class should be the base for all different sorts of vehicles..
If you wanted to make different cars-
Car lambo = new Car(); // New car called lambo
Car truck = new Car(); // New car called truck
Car landrover = new Car(); // New car called landrover
The first part, Car, is the type. Just as you would call a variable.
int num = 5;
A type, integer, called num is equal to 5
Same thing.
A type, type Car, called whatever is equal to something (in this case, a new car/object in which you can set the properties associated with that specific car)
Heres another example
Say you want to make animals. Youd make an Animal class.
Animal pig = new Animal(){name = “pig”}; Creates a new animal object called pig and sets the name property to pig
Animal cow = new Animal(){name = “cow”}
same thing
Hopefully this helped.
EDIT: ill expand a little more to show how all this comes together. I am writing this on mobile so i might make errors.
Thank you for the detailed reply! Question: If the first part is the type “Car” then what is the second part “Car()” called. Because I swear I’ve seen one of the two not the same. I just wish I could find an example to show you.
This is an example of subtyping (https://en.m.wikipedia.org/wiki/Subtyping). If you can perform the assignment:
Then this implies that the type “Truck” is assignable to the type “Car”. This could be due to an implicit conversion operator, but it is more likely that type “Truck” is a subtype of type “Car”. One may also say that type “Truck” inherits from type “Car”. In C# this might be defined like:
Because “Truck” is a subclass of “Car”, then a variable of type “Car” may actually refer to an instance of type “Truck”. However, the following would not work in reverse:
In this example, all Trucks are Cars, but not all Cars are Trucks.
Car truck = new Truck();
So in this example, what type is “truck”? The left hand says it’s type Car, but the right hand says it’s Truck.
Are we saying “It’s Truck, which means it’s necessarily also Car”?
I’m still fuzzy on why you’d declare the variable this way instead of
First of all, welcome to C#!
It is a (mostly) statically typed language, that means objects are of specific Types, and this determines what properties and methods they have, since types are defined somewhere.
To create an object, we use the new keyword, and it takes the Type of the object we want to create from.
But first we must have a Type.
But before we go on, let’s swap the word Car with Vehicle, as it makes more sense here.
Let’s create a Vehicle class. Classes are ways of modelling things, a lot of times real-world objects or concepts. We can’t model every single thing, that would be impossible, so we model an abstraction. We model only the properties of the object we are interested in.
For example, we can say a Vehicle
has a Make
and Model
, and lets throw in the Year
it was made for good measure. Let us declare a Vehicle
Type though it’s class
If we want to create an instance of a Vehicle
, we can write:
Let’s break this up:
This line is really two things. Declaration and instantiation.
It used to be (in old languages) that you had to do things separately.
Declaring something made it so the compiler knew that, hey, this <variable name>
is a variable, and it has this type. So later on it knows that <variable name>
needs to be treated like variable later on, with a type that may have certain properties.
But the boffins realized that you could put them in one statement since most of the time you did that anyway.
Now, speaking of abstraction, in the real world things can have a hierarchy of description. We humans like to be able to categorize stuff, and it extends to code as well.
Let’s look at a Truck. We can say a Truck is a Vehicle. Now, aside from being smart and inventing programming, humans are lazy too. I mean, Do I have to write the whole Make, Model, Year for my Truck? Can’t I somehow say that a Truck is a Vehicle and save time? Can’t I have my cake AND eat it?
Yes, yes you can.
Enter inheritance.
Inheritance allow one class to inherit (bet you didn’t see that coming!) the properties and methods (aka, the information and behavior) of the “base” class. In C# we do this:
And that’s it!
A Truck
now has a Make
, Model
, and Year
. But why? Well we might want some additional properties in the Truck
that are different from or don’t belong in a Vehicle
. Maybe it has more Wheels
. Maybe it has a LoadCapacity
.
myTruck
is now an instance of type Truck
.
But maybe now, all our vehicles need to get registered and need to access the Make
and Model
and Year
. How can we do that? Do we need to distinguish between Truck
s and non-Truck
s?
Since Vehicle
has all the information we need, we can Cast a Truck
to its base class. It’s still a Truck
underneath, but it’s as if we’re putting a filter on top of it and only seeing its Vehicle
aspects. After all a Truck is a Vehicle, right? We declared it as such.
We can cast implicitly. Here the compiler knows that myTruck can be cast down to a Vehicle.
We can also do it explicitly (writing it down verbatim).
Sometimes the compiler can’t guess and you need to specify a cast.
Now that you are accessing it as a Vehicle, you (and the compiler) can only “see” the properties of a Vehicle. The compiler only knows it is a Vehicle and complains if you treat it as anything but.
To pass a Vehicle as a Truck (if it was created as a Truck), you need to cast upwards, explicitly, because the compiler can’t know if it is actually a Truck, or something else, since you told it it was just a Vehicle.
You can’t cast a Vehicle to a Truck, since it doesn’t have any properties that a truck would have, and so would throw an error if accessed as a Truck. C# detects this using the declared Type information during compilation (and while you are coding). This feature is known as type safety.
Fixed formatting.
Hello, rupertavery: code blocks using triple backticks (“`) don’t work on all versions of Reddit!
Some users see this / this instead.
To fix this, indent every line with 4 spaces instead.
FAQ
You can opt out by replying with backtickopt6 to this comment.
Lets say you have a class, Car, and another class, Truck, which inherits from Car.
This is valid because a Truck IS a Car:
Car foo = new Truck();
But the following is NOT because not all cars are trucks:
Truck bar = new Car();
Furthermore, because a Truck is a car, you can pass it as a parameter to any method that takes a Car.
me.DriveCar(myTruck);
DriveCar(Car car){}
When something confuses you, try to break it down into simpler parts. Car car = new Car();
seems very simple, but can in fact be broken down even further. It combines a declaration and an assignment. The following code is equivalent:
Maybe you are overthinking it, at first I got confused too because I thought there was some weird magic done under the hood but it’s more simple than you may think: the new
is what it really is and the declared type is just what you let the code see. Beyond this it’s just a matter of compatibility:
This above is ok because it’s really a truck and trucks are also cars, you are just hiding the fact it’s a truck specifically.
This is not ok because this car is not a Truck, it really is just a Car.
This is ok because you know this one car really is a truck, the code doesn’t know for sure because it only sees a Car at first so you still have to cast it to let it know it’s ok.
Slightly off topic, but does anyone else feel like these methods of teaching software development lead to more confusion than anything?
C# devs
null reference exceptions