TypeScript Tip – Turn a class into an interface

Transcript:

Hello everybody!

In this video I wanted to share a quick TypeScript tip with you. And that tip is that you can create interfaces based off of classes.

Here in front of me I have some code from a game I’m working on.

Don’t worry about the details just focus on line 410 where we have interface ShapeGenerator extending Generator.

Nothing too exciting there if you’ve already seen my video on interfaces, but if we jump to the definition of Generator… You’ll see that it’s a class and not an interface!

It turns out that TypeScript will let you create interfaces from classes, and it does this in an intuitive way: All the public class fields and methods become part of your interface. And then, of course, you can add more if you need them.

Now, why would you want to create an interface in this way?

Well, for this program in particular, I have a number of classes that are based on Generator, but they are all completely separate in their implementation. However, some of them share these three fields, and I want to be able to do things like create arrays of ShapeGenerators.

Create a new interface based off of the Generator class is a super easy way of making it so that I don’t have to repeat all the fields of Generator, and I don’t have to add any extra levels of inheritance just to be able to treat all my similar classes in similar ways.

You won’t need it all the time, but in cases like this, it’s helpful to know that this feature is there.

That’s it for now.

If you want to dive deeper into TypeScript, I’m working on a course called Learn TypeScript by Example. You can find it at https://typescriptbyexample.com/ If you scroll down to the bottom you can put in your email address and I’ll let you know when the course is released.

Thank you so much for watching! I will see you in the next video.

Learn TypeScript #6, Advanced Classes

Transcript:

Hello, everybody! In the previous video we talked about the basics of classes, today we’re going to go a bit more in-depth into the more advanced features of classes. So, let’s get started!

Starting off simple, if you saw the video on interfaces, you’ll remember the “readonly” property. Just like in interfaces, you can mark class fields as “readonly” if you want them to stay constant.

While it may be “read only”, it needs to get an initial value from somewhere. And that somewhere is either in-line here when you declare the field or here in the constructor.

If we try to create a function that changes the name,

You’ll see we get an error “cannot assign to name because it is a read-only property”, which is correct.

So, if there’s a value you want to keep constant throughout an object’s lifetime, readonly is your way of doing that. However, as I mentioned in the previous video on interfaces, read-only is only enforced at compilation time by TypeScript.

Nothing in JavaScript is going to prevent a readonly field from being modified. So if you’re interacting with non-TypeScript code, or with TypeScript code that uses the “any” type a lot, there is a chance that your read only fields could get changed.

Moving on from “readonly” properties, let’s talk about static properties.

If you’re familiar with the term “static” from physics, this is nothing like that at all. “static” is a fancy keyword that lets us define properties on the class itself, rather than on the instances of the class.

For example, we might want to keep track of the number of Player instances that we have created. We could do this by creating a static playerCount field, and then incrementing that by one in the Player constructor.

If we scroll down in the code a little and try to access “p.playerCount”, you’ll see that is an error.

To actually access the the player count, we’ll need to do capital P Player.playerCount.

Static properties are helpful for anything that you want to share across all instances of a class. Frequently you’ll see them used to contain constants that are the same across all instances.

For example, players might have a maximum speed that they can move at, so we could create a static “maxSpeed” field to hold that value.

Similarly to normal fields, static fields can be read only so if maxSpeed is never going to change throughout the course of the game, then it would make sense to mark it as read only to ensure that we don’t accidentally change it in some other part of our program.

Now, if you’ve used any other object-oriented programming language such as Java or C#, you’re probably familiar with public, private, and protected members of a class. TypeScript has the same concepts.

In the previous video, I mentioned that all fields and methods are publicly accessible by default, and that means that the “public” keyword is implied on every field and method.

So while we could put the “public” keyword in front of all of these definitions, there’s no real need to do, since it’s equivalent to putting nothing there at all.

Now, one of the principles of good object-oriented design is that you should provide a simple, clean public interface to your object, and hide all the gory implementation details that aren’t relevant to other parts of your program.

This makes it easier to change the internal workings of a class without worrying about breaking any other part of your program, and it prevents internal methods from being misused.

To illustrate this, let’s imagine that for every frame in our game, we want objects to be able to run any logic they need to run to keep the game moving forward. To facilitate this, we’ll change our GameObject interface to include an “update” method that will contain this logic.

So, our Player class is going to need to implement this update method.

Now in order to properly move the player, there might be some complicated physics calculations that we need to run. Let’s create a “calculateMotion” method to represent that.

The logic in “calculateMotion” won’t be relevant to any other object in the game, and we don’t want anybody accidentally calling it and doing something like moving our player twice, or something else equally as weird. So it makes sense to mark it as “private”.

The “private” keyword makes it so that only the class itself can use the method or field. If we scroll down and try to call “calculateMotion” on the instance of our Player class, TypeScript gives us an error saying it’s only accessible within the class itself.

It’s important to understand that private fields and methods don’t count towards whether or not something implements an interface. Say if we set the “z” variable to private, we’ll get an error that Player incorrectly implements the GameObject interface.

Even though technically the Player has that field, nobody can use it and so TypeScript correctly calls that an error.

One other thing to note is that similar to readonly, the public-private distinction is only handled by TypeScript at compile time.

If we open up our compiled JavaScript file, you can see we’ve got our “calculateMotion” method and we’ve got our “z” variable and there’s nothing different about these compared to anything else in this file.

Nothing in the resulting JavaScript code is actually enforcing that these properties are private. TypeScript will prevent you from accessing them improperly in your TypeScript code, but when we get to the JavaScript runtime, everything is public and accessible.

This is helpful for debugging, but if you’ve got a situation where one TypeScript team of developers is working with another plain JavaScript team of developers, you’ll to make sure to communicate what’s private and what’s public.

Alright, I mentioned earlier that there was one other level between public and private, and that’s “protected”.

A “protected” field or a “protected” method is similar to private in that only the class itself can access the property, but with the added distinction that if you have another class which inherits from your class, that child class is able to access the property without restriction.

We haven’t talked about inheritance yet, so I’ll show you a more concrete example of this in a few minutes.

One other thing that I wanted to mention before we move on, is an alternate way of writing what we’re doing with the name field.

Currently we’re declaring it as a public field, and we’re setting its value directly from the constructor argument.

This is actually a really common pattern, and so TypeScript has a way of doing it in 1 line rather than 3.

Let’s get rid of our declaration line, and our “this.name = name” line, and instead we’ll simply put the “public” keyword in front of the name argument.

This has the exact same effect as the 3 lines we had earlier: “name” is declared as a public property, and when it’s passed into the constructor as an argument, it gets directly assigned from that argument value.

This is exactly equivalent to what we had earlier.

Just to be clear, this works for any of the accessibility modifiers except for “static”, so if we wanted this to be “protected readonly” instead of “public”, that is a perfectly valid thing to do.

If we run our program, you’ll see everything is doing exactly what we’d expect.

Okay, on to inheritance!

At a high level, inheritance is a feature that let’s you create new classes that are based on the implementation of existing (parent) classes.

For an example of how to use inheritance, let’s say that for the game we’re making, we’ll have different types of players that share some common functionality.

So our existing Player class is where all the common functionality will be stored, and then we’ll create more specific classes for each type of player that will include whatever differentiates that specific type.

Let’s say that in our game, one type of Player will be able to shoot at enemies with guns. To support this, we’ll create a Gunner class.

We’ll write class Gunner extends Player.

And what this will do is cause Gunner to “inherit” all the fields and methods that the Player has.

Gunner will have an x, y, and a z position. An update method. And so on. Anything new we add to Player will also end up as a part of Gunner.

Even the constructor is carried over, so we could swap out our usage of new Player to new Gunner. And if we go to our Terminal and run that.

You can see Node.js telling us this is now an instance of the Gunner class, but otherwise everything else is working exactly the same as it did thanks to inheritance. Since Gunner has everything Player does, we can treat our Gunner exactly like a Player.

Going back to Gunner’s implementation, we can add things to this in exactly the same way we can add fields or methods to any other class.

For example, we could add a field that keeps track of the number of bullets.

Let’s say that in addition to the name of the Gunner, we want the type of the gun to be specified when a new Gunner is created. We’ll start by creating a new constructor that takes both a name and a gunType.

You’ll see that TypeScript is giving me an error “Constructors for derived classes must contain a super call”. What does that mean?

It means that in order for our object to be properly constructed, we must call the constructor of our parent Player class. You can do that by using the super keyword, and then we’ll give it whatever arguments that the Player constructor needs. Here we’ll just pass in our name, and everything will be happy.

The super keyword is also used to refer in general to any other method you may want to call on the parent class.

Say, for example, we wanted to have our own custom update function for our Gunner. Perhaps every frame they should gain an additional bullet that they can shoot.

But, we still want to use the same movement logic that is defined in our parent class. So we’ll need to call Player.update(). We can do this by adding a call to super.update() as part of our update method, and then that original method will be called.

It’s important to note that that without the super.update() call, the Gunner class would have it’s own completely isolated implementation of update(), the original update code defined in the Player class would go unused in Gunner.

This is often a valid option, as some classes may want to completely override whatever functionality their parent class had implemented.

Previously we mentioned protected fields as an alternative to private fields. Let’s show an example of that here. We’ll change our calculateMotion() method to be protected.

And you’ll see if we try to call calculateMotion() within our Gunner’s update method, that’s perfectly acceptable.

However, if we change calculateMotion() to be private instead of protected, Gunner’s use of that method becomes an error.

So, the protected modifier lets subclasses access the field or method, private keeps it so that only the things within the bounds of that original class definition can access it. Both private and protected prevent access from any other part of the program.

Another inheritance feature that is frequently used is something called an “abstract class”.

An abstract class is a class that’s not meant to be used on its own.

As we said earlier, this Player class is meant to contain functionality common to all player types, but we’ll probably never want to create just a generic player.

This means it’s a good candidate to become an abstract class.

If we add the abstract keyword, you’ll see down below in our code we get an error where we’re directly creating an instance of Player. You cannot create an instance of an abstract thing. We’ll have to switch that to Gunner.

The abstract keyword also comes into play in one other place: method declarations.

We can put the abstract keyword in front of our update method, and this will indicate that this is something we want all child classes to implement, but the parent class won’t be providing any sort of default functionality itself.

If we go this route for our game, this is basically equivalent to saying that we know every different type of Player will need to update itself in some way. But the exact details of how they update will be so varied, that there’s no point in providing some sort of default implementation.

Just to show you that this is being enforced, if I remove the update method on Gunner, you’ll see that we are now getting a complaint about “Non-abstract class Gunner does not implement inherited abstract member update from class Player”.

And that wraps it up for this video!

If you’re interested in going deeper with TypeScript, I’m working on a course called Learn TypeScript by Example.

You can find it at https://typescriptbyexample.com If you scroll down to the bottom, you can put in your email address and I will let you know when the course is released!

Thank you so much for watching! I will see you in the next video.

Learn TypeScript #5, Basic Classes

Transcript:

Hello, everybody! Today I’m going to show you how to use classes in TypeScript. There’s a lot to cover about classes, so for this video we’re going to stick to the basics, and then in future videos we’ll dig into the really advanced stuff.

At their core, classes are a way of describing what data you want certain objects to hold, along with methods that act on that data in various ways. There are a lot of other features built on top of this, but that is the core.

If you come from a language like C# or Java, classes in TypeScript are very similar to what you worked with there. Though there are some important differences in the low-level details, which we’ll be covering in later videos.

Unlike Java or C#, however, there’s nothing in TypeScript that is forcing you to use classes. So if you prefer to write your code in some other way, you are perfectly free to do so. Classes are just another tool you have in your toolbelt as a TypeScript developer.

If you’ve been following the development of JavaScript over the years, you’ll know that the latest JavaScript standards have added support for classes. TypeScript classes build directly on these standards, but with the added benefit that you can use TypeScript to target older versions of JavaScript, and the classes you write will work perfectly well when compiled down to code that’s compatible with older browsers that don’t support classes in JavaScript directly.

So let’s start off with a simple example class.

Let’s say we’re making game and we’re planning on having multiple players and a decent amount of logic common to the players to handle things like movement, displaying the players, and so on. This sounds like a good candidate for a class, so let’s create a class called Player.

Creating a class is very simple, we’ll write the class keyword followed by our class name, and then the contents of the class are contained within curly brackets. If you saw the previous video on interfaces, you’ll notice that class definitions and interface definitions share a lot of parallels, which you’ll see more of going forward.

Let’s pause for a moment and note that this is actually a complete class. It’s empty, so it’s not very useful, but before we start putting things in it, I want to show you how to create an instance of this class.

We’ll create a new variable called “p”, and set it equal to “new Player()”.

The “new” keyword is how you indicate that you’d like a new instance of an object that’s defined by a certain class. Player is obviously the name of your class, and your parentheses indicate that this is a function call.

Now, we haven’t actually defined any function here, so what function is it calling? Well, all classes have what are called “constructor” functions, and if you don’t create one explicitly, TypeScript will create one for you. We’ll go into more detail on this in a bit.

Let’s log the variable and see what it looks like.

You’ll see that Node.js is actually very helpful here, showing us the class name, and then the empty curly brackets will contain the data in our object once we actually start adding some fields to our class.

So, how do we add things to our Player class?

The first and easiest way is to simply write the name of the variable, and then assign to it whatever value you want.

Here we’ll say each player needs and x and a y position, so we’ll set both of those equal to zero.

If we run our program again, you’ll see that I have a player with an x and y of 0. Excellent!

These fields are just like the fields of any other object. For example, I can set “p.x” equal to 1, and that will do what you expect.

A note to those from other programming languages: Fields in TypeScript are all publicly accessible by default.

Just to prove to you that we have an isolated instance of our object, let’s create a second variable called p2, and log that one out as well.

And you’ll see it’s only our original object that has changed, just as we would expect.

Going back to our class definition, note that if you wanted to be explicit about the type that you wanted a field to be, you can indicate that in the usual way by simply writing a colon and then the type that you’d like.

What we’ve done so far works well for fields that will always start off at some default value, but what about a case where there isn’t necessarily a correct default value?

For example, let’s say we wanted to give each Player a name. We’ll add the name field and say that it should be a string.

But, what’s a good default for that? Well, an empty string might not make much sense there. Neither would a random name. Plus then we’d have to remember to change it properly after instantiating it.

Probably what makes most sense would be for us to force the name to be specified at the creation of the object. We mentioned previously that there was a constructor function being created for us, let’s define it ourselves now so that we can use it to require a name.

You can do that by going to the class definition, typing “constructor”, parentheses and then curly brackets for the constructor function body.

We’ll add “name” as a parameter to this function, and we’ll assign “this.name” equal to the “name” parameter.

You’ll see that now TypeScript is giving us errors about the places where we’re creating instances of this class because we’re not providing a name.

Let’s name the first one “Tyler” and the second one “Fred”. And now TypeScript is happy again.

A couple points of clarification on constructor functions. First, the special “this” keyword refers to the particular instance of the class that you’re currently working with. Here in the constructor, that’s the newly created object that we’re building up.

Second, the way these default values for x and y are set by TypeScript is by moving the assignment to the very top of your constructor function.

So assigning a value to them on the same line as their definition is directly equivalent to writing “this.x = 0” at the top of the constructor function.

In general, since assigning the default value where the field is declared is more compact than the alternative, I tend to favor doing that in my own code. If you prefer to leave the declaration as only the types, and initialize all the defaults in the constructor that’s a perfectly valid stylistic choice.

Note that if you’re initializing something in the constructor, the field declaration must have a type on it, because otherwise TypeScript will not be able to infer what type it is that you want.

Okay, so we’ve got some data that we’re holding in our objects, let’s create a function to act on that data.

Let’s say we don’t think the output of console.log is quite to our liking, so we’d like some other way of displaying our Players.

Well, we can create a new method by specifying the name, the arguments in parentheses, and then we can specify the return type with a colon after the parentheses.

And we’ll type out a call to console.log() that formats things a little more nicely.

And we’ll run that, and hey! Things are looking pretty good.

One thing you’ll notice down below is that the list of functions that are part of an object aren’t included in the default console.log() output in Node.js. Generally this is fine, since the data will be more important to see, but this is something you should be aware of.

Let’s tie things into the previous video by showing how we can make interfaces and classes work together.

Since we’re working on a game here, I imagine we’ll have a number of different types of objects that we’ll want to treat generically in some kind of way. Perhaps we’ll use some common fields to do collision detection or to draw them or whatever else.

To define what we need, we can create an interface listing what we’ll need from each game object.

Let’s say this is a 3D game, so we’ll need an x y and z position.

In order to indicate that we want our player to be compatible with this interface, we can use the “implements” keyword followed by the name of the interface. Note that if you had multiple interfaces, you can separate them by commas.

Now we’re getting an error about our player not implementing the interface correctly because it doesn’t have the “z” field, so let’s add that.

And now everything is good.

Down lower in the code, we can create an array of GameObjects, and put our two player objects in that array. Since our Player class properly implements the GameObject interface, TypeScript is perfectly happy with this.

Note that the “implements” keyword on our class definition isn’t actually required as you might be used to from other languages. If we remove it, everything is still fine. The difference here is that if we were to remove our “z” field, we now get an error down in our array rather than on the class itself.

So why would you want to use the implements keyword if you can get away without it?

The biggest reason is that it will tell you while you’re focused on just the class definition itself whether or not the class properly implements the interface.

It also serves as great documentation for your future self and other programmers that the specific class is intentionally conforming to some interface.

A third reason, is that some frameworks like Angular will check objects for specific methods. If they exist, Angular will call them, if they don’t, Angular won’t. Including the “implements” keyword and the relevant interface for that specific Angular feature will cause TypeScript to validate that you are actually including that method properly. If not, you’ll get an error, which is helpful.

Okay, we’ll pause here and in future videos we’ll be covering things like inheritance, private, public, and protected fields, static properties, accessors, the nitty gritty details on the implementation details behind classes, and much more.

If you’ve enjoyed this video and want to go deeper, I’m working on a course on TypeScript. You can find it at https://typescriptbyexample.com I’m still working on it but if you scroll down to the bottom of the page leave your email address there I’ll shoot you an email when that course is released.

That’s it for this video! Thank you so much for watching, I will see you in the next one.

Programming With Ruby Episode 4, Main Ruby Concepts


Covered In This Episode:

  • Basic Variables
  • Basic Methods
  • Basic Classes
  • Interactive Ruby (irb)

Code:

# Define the class Greeter
class Greeter
	# Define the method hello
	# This method greets the
	# user
	def hello(name)
		puts "Hello " + name
	end # End of the method hello
end # End of the class Greeter

Greeter.new.hello("Tyler")


Transcript:

Hello everybody and welcome to Programming With Ruby Episode 4, Main
Ruby Concepts.

Covered in this episode. We’ll be playing with interactive ruby (also

called irb). I will teach you about variables, basic methods, and

classes in Ruby. Lets get started!

Basics Description

Ruby is an object oriented programming language. object oriented
languages use objects. Ruby goes beyond most other object oriented
languages, because in Ruby, everything is an object. (I’ll show you
exactly what that means in a few minutes)

Object oriented programming sort of models real life. Look around you,
everything around you is an object. Your computer, your desk, books,
the moon, and people are all objects.

In programming, all objects have properties called variables. These
could be the color of the object, the weight, size, or any other kind
of property.

Objects also have methods (which are sometimes called functions). A
camera object would have a method to take pictures. A car would have a
method to drive. A printer would have a method to print.

As well as making code easier to understand, you will also continue to
appreciate other benefits of object oriented programming further on in
your programming career.

Example

I have written a very basic Ruby program. This is about what most
programs look like, just a lot simpler. Let’s break it down line by
line.

Everything followed by a hash mark (#), is ignored by Ruby. These are
called comments. In these comments you can describe what your code is
doing, make notes to yourself, and other such things.

The first line says “class Greeter”. This line tells Ruby that we are
now defining a class named “Greeter”. Please remember that all classes
in Ruby start with a capital letter!

The next line says “def hello(name)”. This line means we are defining
a function (def), named “hello”, that takes the parameter “name”.

The following line is a little trickier. ‘puts “Hello ” +
name’. “puts” means “put string”. our string is “Hello ” + name. Now
you’re probably wondering what the “+ name” is for. We’re aren’t doing
math on strings, but we are connecting the variable “name” to our other
string “Hello “.

The next two lines have the keyword “end”. The first end means we are
done defining the function “hello”. The second “end” means we are done
defining the class “Greeter”.

Below where the class “Greeter” ends we have the line ‘myname =
“Tyler”‘. This means are creating the variable myname and placing
“Tyler” inside of it.

Next is, the line “person = Greeter.new”. This means we are
instantiating a new greeter object named person.

Finally we have the line “person.hello(myname)”. This calls the
person object’s method “hello” and passes the variable “myname” as an
argument.

Now lets run the program. If you remember, to run a program you open
Terminal or Command Prompt, change directories into where you saved
your program and type “ruby programname.rb”. In my case I will type
“ruby episode4.rb”.
And there you have it, it says “Hello Tyler”

The code in this example will be available in the YouTube video
description, and below this video on manwithcode.com

Example 2
Back to the code. This code is actually a little longer
than it has to be. I did this so things would hopefully make more
sense. In reality we can change the last three lines to
‘Greeter.new.hello(“Tyler”)’

We can do this because in Ruby, everything is an expression. Here’s how
it breaks down. “Greeter.new” creates a greeter object. “.hello” calls
the method “hello” on that new object. And then we pass in the string
“Tyler” as an parameter.

Ruby has many other tricks like this to make your code shorter. Some
have disadvantages and others do not. One of the most important
disadvantages can be clarity or readability. You want your code to be
as easy to understand as possible.

irb
Interactive Ruby (or irb for short). irb makes it very easy to
quickly test out code, find out if/how something works, do basic math,
and write throwaway code you will only use once.

To open irb, open up your Command Prompt or Terminal and enter
irb. Alternatively, if you are on Windows, go into All Programs and
under Ruby will be a program name fxri which is an equivalent to irb.

In irb you can do basic math:

2 + 2 #=> 4
2**6 #=> 64
2 * 5 #=> 10

We can write any valid Ruby code. So we could write the greet method again.

def greet(name)
    puts "Hello " + name
end

And then call it:

greet("Tyler")

Remember earlier I said everything in Ruby was an object? I’ll show
you what I mean. if you type in the name of an object and call the
class method it will tell you its class.

0.class #=> Fixnum
"Hello".class #=>; String
String.class #=> Class

I encourage you to play around with irb for a little while, try
writing your own methods, and have some fun with it.

End
This brings us to the end of this episode, I hope it helped
you.  If you need any help, have questions or comments, leave a
comment below or contact me at tyler@manwithcode.com

Don’t forget to donate! There is a donation link to the right of this
video. On YouTube its in the description box. On my website, it is to
the right of the video.

Thanks for watching! Bye!