# Stopwatch Part III: Stopwatch in TypeScript

**URL:** <https://forum.makecode.com/t/stopwatch-part-iii-stopwatch-in-typescript/8369>\
**Category:** Arcade\
**Created:** [May 28, 2021, 4:35am UTC](https://forum.makecode.com/t/stopwatch-part-iii-stopwatch-in-typescript/8369 "2021-05-28T04:35:23Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![AlexK](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/alexk/32/33339_2.png) [@AlexK](https://forum.makecode.com/u/AlexK)\
**Post date:** [May 28, 2021, 4:35am UTC](https://forum.makecode.com/t/stopwatch-part-iii-stopwatch-in-typescript/8369/1 "2021-05-28T04:35:23Z")

</div>

Now, let’s create the Stopwatch in TypeScript. This will move us closer to creating a Stopwatch extension.

If you have not created the Blocks version of the stopwatch, you may want to review the first two posts in this series:

- [Part I: Basic stopwatch](https://forum.makecode.com/t/making-a-stopwatch/3814)
- [Part II: Advanced stopwatch](https://forum.makecode.com/t/stopwatch-part-ii-advanced-stopwatch/3827)

# Introduction

In this post, we will create the stopwatch using TypeScript. We also will talk about some basics of object-oriented design. We won’t go into a lot of detail; we will just highlight some of the concepts.

## TypeScript

We will be using TypeScript for this project. (You may know it instead as _JavaScript_, since that is what the language is called in the editor.) We will not cover the basics of TypeScript here. If you want to learn TypeScript, then take a look at the [**CS Intro 3** course](https://arcade.makecode.com/courses/csintro3) in the MakeCode Arcade documentation.

# Finished code

Here is a link to the finished version of the project. Feel free to run the project in the simulator. As before, if you’re planning on walking through this journey with me, then please don’t look at the code yet. You don’t want to spoil the story! 🙂

> **[Stopwatch III JS](https://arcade.makecode.com/27488-01131-91584-95372)**
>
> Made with ❤️ in Microsoft MakeCode Arcade.

We will come back to this project later, as the code that we create together will be a little bit different from the code in the project above.

# Working with the Text Sprite in TypeScript

> **Installing the Text Sprite extension**
>
> First, let’s work with the **Text Sprite** extension in TypeScript to get a feel for it. To begin, we’ll create a new project and install the extension.
> 
> 1. From the **Home** page, create a new project. Give your project an appropriate name, like “TypeScript Stopwatch”.
> 2. Switch from **Blocks** to **JavaScript**.
> 3. Install the extension just like you did in Blocks mode.
> 1. In the toolbox, open the **Advanced** section.
> 2. From the **Advanced** section of the toolbox, open the **Extensions** panel.
> 3. Search for _arcade-text_.
> 4. Click on the **arcade-text** extension to add it to your project.

> **Using the Text Sprite extension in TypeScript**
>
> Now, let’s create the same Text Sprite that we created in Blocks for our stopwatch. Feel free to copy-and-paste the following code. We’ll take a look at it together.
> 
> ```typescript
> let textSprite : TextSprite = textsprite.create("0")
> textSprite.setMaxFontHeight(12)
> textSprite.setOutline(1, 2) // 2 == red
> textSprite.setIcon(img``)
> textSprite.x = 80
> textSprite.y = 6
> 
> ```
> 
> In line 1, we create the Text Sprite and set the initial text to “0” using something called a **factory function**. We will talk a little more about factory functions later. The remaining five lines (lines 2 through 6) set the options for the Text Sprite that we created, just as we did in Blocks:
> 
> - In line 2, we set the font size to 12 pixels.
> - In line 3, we set the outline of the text to one pixel in size, and we set the color to red.
> - In line 4, we set the image that will appear next to the text. (The image is empty for now.)
> - In line 5, we set the horizontal (or **x** ) coordinate of the Text Sprite.
> - In line 6, we set the vertical (or **y** ) coordinate of the Text Sprite.
> 
> Feel free to create an image that will appear next to the sprite. Click on the artist’s pallette next to line 4. The image editor will open, and you will be able to create your image. Set the image’s size to 12 x 12, which matches the font size that we are using.
> 
> Run the project in the simulator if it is not running already. You will see that we already have created a Text Sprite, ready for us to use as a stopwatch! All with only six lines of code!

> **Factory functions**
>
> In the previous section, I mentioned that we used a factory function to create our text sprite. A _factory function_ is a standalone function that creates variables for us, often simplifying the process. Factory functions are used a lot in MakeCode extensions to simplify things a bit for the Blocks environment. While designed for the Blocks environment, factory functions are useful in our TypeScript projects, too, to make things a bit simpler.
> 
> In our current code, we use a factory function to create our Text Sprite, and it works great! Because of how we are going to design our stopwatch application, though, we are going to have to make the code a little more complicated.

> **Replacing factory function**
>
> Because of how we are going to design our stopwatch application, we need to replace the call to the factory function. While it makes our code a little more difficult to read, we get to replace three lines of code with just one!
> 
> Replace the first three lines of code with this one:
> 
> ```typescript
> let textSprite : TextSprite = new TextSprite("0", 0, 1, 12, 0, 0, 0, 1, 2)
> 
> ```
> 
> Your code now should look something like this:
> 
> ```typescript
> let textSprite : TextSprite = new TextSprite("0", 0, 1, 12, 0, 0, 0, 1, 2)
> textSprite.setIcon(img``)
> textSprite.x = 80
> textSprite.y = 6
> 
> ```
> 
> In this new line of code, we are using the **constructor** for the Text Sprite class. A _constructor_ creates an object out of a class. It’s OK if you are not familiar with those terms. I’ll talk about them again later. The thing to notice, though, is how the factory function simplified the creation of our `textSprite` variable. The `textSprite.create()` function only required one parameter: the initial text to display. The constructor function that we are using now, though, requires **nine** parameters. Notice, too, that those nine parameters include the options that previously configured with additional lines of code: the 12 for the font height, the 1 for the size of the outline, and the 2 for the outline color.

# Object-oriented design

> **Introduction**
>
> When we write programs for computers, we follow a **programming paradigm**. A _programming paradigm_ describes both the structure of programs and how data moves within them.
> 
> When we write programs in Blocks, we involve two programming paradigms:
> 
> - In **structured programming** , we create functions to help us break down a problem into smaller parts. We also use functions to help us reuse code. We create variables to store data; in Blocks, those variables are available to all parts of our program. (These are known as _global variables_.)
> - In **event-driven programming** , our programs respond to _events_ – things that happen in our program. Some events are triggered by the user (like a button press); other events are triggered by the program itself (like when two sprites overlap).
> 
> Structured programming is an _excellent_ programming paradigm. It’s the paradigm that I used when I was learning computer programming as a youngster, and most of the major programming languages support structured programming. With structured programming, you can learn all three fundamental constructions in programming:
> 
> - **Sequence** : Performing a series of steps in a specific order
> - **Decision** : Running different pieces of code depending on a condition (also known as _branching_)
> - **Loops** : Repeating a set of code multiple times (also known as _iteration_)
> 
> For languages that support it, though, there is another programming paradigm: **object-oriented programming** , or **OOP** (usually pronounced as you would say the word _oops_). In object-oriented proramming, instead of breaking programs into functions, we break programs apart into **objects**. _Objects_ are collections of variables and functions (they’re often called _methods_ in OOP) that share something in common.
> 
> While Blocks offers a simplified form of object-oriented programming (through the **arcade-sprite-data** extension), TypeScript fully supports object-oriented programming. We will take advantage of TypeScript’s support of object-oriented programming for our Stopwatch application.

> **Class diagrams**
>
> When designing a program using object-oriented design, we often create **class diagrams**. _Class diagrams_ visually display the data and functions that we group together, and they also display how different classes of information are related to each other.
> 
> For example, here is a class diagram of the **Text Sprite** class:
> 
> ![1](https://us1.discourse-cdn.com/flex020/uploads/makecode/original/2X/6/61f1a7bf38aacbbe8d0f4d16ef21f6bcf575d934.png)
> 
> Let’s recall the code that we wrote earlier that created and manipulated a text sprite:
> 
> ```typescript
> // First version
> let textSprite : TextSprite = textsprite.create("0")
> textSprite.setMaxFontHeight(12)
> textSprite.setOutline(1, 2) // 2 == red
> textSprite.setIcon(img``)
> textSprite.x = 80
> textSprite.y = 6
> 
> // Second version
> let textSprite : TextSprite = new TextSprite("0", 0, 1, 12, 0, 0, 0, 1, 2)
> textSprite.setIcon(img``)
> textSprite.x = 80
> textSprite.y = 6
> 
> ```
> 
> In both versions of our code, we created an **object** that we called `textSprite` (with a lowercase _t_). That object was created from the class called **TextSprite** (with a capital _T_). The class name also is known as the object’s _type_, in the same way that we create variables of type **int** , **bool** , or **string**.
> 
> In our code, we also call functions **on** our object, like `textSprite.setMaxFontHeight()`. Notice that these methods appear in our class diagram for **TextSprite**. These functions “belong” to the **TextSprite** class, and these functions can be called on any object created from the **TextSprite** class.
> 
> Notice, too, in the class diagram that **TextSprite** objects have **properties** , like `outlineWidth`. Each object that is created out of this class will have its own set of properties. (They’re sometimes known as _attributes_.) So, one object (i.e. one text sprite) may have an outline width of 1, like in our sample project. Another object in the same program could have an outline width of 0 instead. In our sample program, we used the method `setOutline()` to change the width of the outline. We also could have written something like this:
> 
> ```typescript
> textSprite.outlineWidth = 1
> 
> ```

> **Inheritance**
>
> The objects created from the **TextSprite** class have other properties, like `x` and `y` for setting the text sprite’s location on the screen. If you look back at the class diagram, though, you will not find properties called **x** and **y**. Why is that?
> 
> The **TextSprite** class is not a standalone class. Instead, it depends on another class. A **TextSprite** , after all, is still a **Sprite**. In object-oriented terms, we say that the **TextSprite** class **inherits** from the **Sprite** class. We can show that in our class diagram:
> 
> ![2](https://us1.discourse-cdn.com/flex020/uploads/makecode/original/2X/d/dda6f24849a44c75b09fc4a5120ba62ad7aeeb2d.png)
> 
> The big arrow that links the **TextSprite** class with the **Sprite** class indicates _inheritance_. Because the **TextSprite** class inherits from the **Sprite** class, _everything_ that works with a sprite will also work with a text sprite. You can change a text sprite’s location just as you can change a sprite’s location. You can give a text sprite velocity and acceleration, just as you can with any other sprite.

# Creating the **Stopwatch** class

> **Adding a file to the project**
>
> While you can write the code for our new class in the main file, we typically put classes into separate code files. Let’s create a new file for our **Stopwatch** class.
> 
> 1. Beneath the simulator, click on **Explorer** to reveal the file explorer for our project.
> 2. When the file explorer is expanded, a **plus sign** appears next to the word _Explorer_. Click on the plus sign to add a file to our project. A dialog appears on the screen.
> 3. Give the new file the name **stopwatch.ts**.
> 4. The new file opens in the editor.
> 5. Switch back and forth between the **main.ts** file and the **stopwatch.ts** file. Also, feel free to explore the other files that are in your project.

> **Creating the Stopwatch class**
>
> Let’s create the initial version of our Stopwatch class. It will not look like much … but we get a lot of functionality out of this little bit of code!
> 
> _ **stopwatch.ts** _
> 
> ```typescript
> class Stopwatch extends TextSprite
> {
> }
> 
> ```
> 
> The class diagram for our application now looks like the image below. I’ve simplified the diagram for **TextSprite** just to make the image a bit smaller.
> 
> ![3](https://us1.discourse-cdn.com/flex020/uploads/makecode/original/2X/0/0930226abac20e0e642511add80e3e3d1e601098.png)
> 
> Now, switch back to **main.ts** and change the first line of your code to use our new class.
> 
> _ **main.ts** _
> 
> ```typescript
> let textSprite : Stopwatch = new Stopwatch("0", 0, 1, 12, 0, 0, 0, 1, 2)
> 
> ```
> 
> Pause for a moment and take this in. We have written **no code at all** for our **Stopwatch** class. **None.** However, because it inherits from the **TextSprite** class, we get all of its functionality!

> **A new constructor**
>
> Whenever an object is created from a class, a special function called a _constructor_ is called. That’s what is happening in the first line of **main.ts** – an object from our new **Stopwatch** class is created, which calls the constructor function.
> 
> Let’s help out our users a bit, though, by writing a new constructor that’s simpler. Right now, we are using the constructor for the **TextSprite** class, which requires nine arguments. Let’s make some assumptions and shrink that down to zero.
> 
> In the **Stopwatch** class, create a constructor. Because the constructor takes zero arguments, it is known as a _default constructor_. The code for the entire class is shown below so that you know where to write the code for the constructor. Notice that the code for the constructor is very similar to the code that you already have in **main.ts**.
> 
> _ **stopwatch.ts** _
> 
> ```typescript
> class Stopwatch extends TextSprite
> {
> constructor()
> {
> super("0", 0, 1, 12, 0, 0, 0, 1, 2)
> this.setIcon(img``)
> this.x = 80
> this.y = 6
> }
> }
> 
> ```
> 
> Our class diagram now looks like this:
> 
> ![4](https://us1.discourse-cdn.com/flex020/uploads/makecode/original/2X/0/04ff0d779cc758c8a7d88a6e252a6af0e4e9cc28.png)
> 
> Let’s go through this code:
> 
> - The first line calls the constructor function in the **TextSprite** class – the class from which we are inheriting. (It’s also called our _superclass_ or _parent class_ for **TextSprite**.) This sets the initial text to “0”, sets the outline to 1 red pixel, etc… all of the things that it did when we used it in **main.ts**. We still need all of those things to happen, so we call that constructor here. To call the constructor of our parent class, we use the keyword `super`.
> - The second line sets the icon, the third line sets the horizontal coordinate, and the fourth line sets the vertical coordinate, just as it does in **main.ts**.
> - Notice that those three lines use the keyword `this`. When we are working with objects within our class, we do not know the objects’ names. So, when we are manipulating an object within its own class, we use the keyword `this` to represent that object.
> 
> Now, back in **main.ts** , because we are doing all of this work already in the constructor, we can replace _all_ of the code with just this one line:
> 
> _ **main.ts** _
> 
> ```typescript
> let sw : Stopwatch = new Stopwatch()
> 
> ```
> 
> Now, if our users want to change the icon, text outline, or location, they certainly can, using code similar to what we used to have in **main.ts**. We’re simply offering some initial settings that seem reasonable.

# Adding functionality to the **Stopwatch** class

> **Planning functionality**
>
> We have our **Stopwatch** class functioning as a customized text sprite. Now, we need to add functionality so that objects work like stopwatches.
> 
> Think back to the Blocks version of the stopwatch. What functionality did we introduce? What information did we have to store and manipulate? How did we interact with the stopwatch?
> 
> Now, think about our **Stopwatch** class, perhaps in its visual form with its class diagram. Remember that objects store data in the form of properties (or attributes). Objects also have functions (or methods) that can act upon their properties. What properties would you add to our class? What functions are needed?
> 
> Consider those questions and their answers. Then, move on to the next section, where we add to our class diagram.

> **Adding to the class diagram**
>
> In the Blocks version, we created these variables to keep track of information related to the stopwatch:
> 
> - `timerIsRunning` : boolean
> - `startTime` : number
> - `accumulatedTime` : number
> 
> We also created the following functions:
> 
> - `startTimer()`
> - `stopTimer()`
> - `resetStopwatch()`
> - `updateStopwatch()`
> 
> Let’s incorporate these into our class diagram. Because we are adding these to the **Stopwatch** class, we know that all of these things are related to **Stopwatch** objects. We’ll simplify some of these names.
> 
> ![5](https://us1.discourse-cdn.com/flex020/uploads/makecode/original/2X/4/4c19f32cf32776da5237b52c5dd5bc9c9d66d5f8.png)

> **Adding code and connecting controls**
>
> Before we dive into the code for these functions, we’ll just add “function stubs” to our class. They won’t have any functionality just yet, but we can still call them.
> 
> Head over to **stopwatch.ts** and add the code that you see below. You already have the code for the constructor, so I’ll leave it out to shorten this code snippet.
> 
> _ **stopwatch.ts** _
> 
> ```typescript
> class Stopwatch extends TextSprite
> {
> public isRunning : boolean = false
> public startTime : number = 0
> public accumulatedTime : number = 0
> 
> constructor()
> {
> /* You have code here; keep it! */
> }
> 
> public reset() : void
> {
> }
> 
> public start() : void
> {
> }
> 
> public stop() : void
> {
> }
> 
> public update() : void
> {
> super.update()
> }
> }
> 
> ```
> 
> You may be asking yourself: “What does that word `public` mean?” We won’t go into details on **access modifiers** like public, private, and protected. For now, we will make all of our class members public so that we can access them from outside of the class. (The properties and methods of a class, together, are known as the class _members_.)
> 
> You also may notice that we have more than a stub for the `update()` function. And there’s that keyword `super` again! Briefly: The parent class, **TextSprite** , alredy has a function named `update()`, and it’s called whenever the sprite changes and needs to be drawn on the screen. If we leave our `update()` function empty, then the sprite never gets drawn on the screen. So, whenever `update()` is called for a **Stopwatch** object, the function in the **TextSprite** needs to run, too. We call **TextSprite** ’s version of the function with the `super` keyword, similarly to how we used it in our constructor.
> 
> Now that we have these functions available, let’s hook them up in our main code file. Remember that, when the user presses **A** , the stopwatch starts or stops. When the user presses **B** , the clock resets to zero. We also should update the sprite in the game update loop if the stopwatch is running.
> 
> Let’s add those pieces of code to our **main.ts** file. Use the toolbox to add code snippets as needed.
> 
> _ **main.ts** _
> 
> ```typescript
> let sw : Stopwatch = new Stopwatch()
> 
> controller.A.onEvent(ControllerButtonEvent.Pressed, function() {
> if (sw.isRunning) {
> sw.stop()
> } else {
> sw.start()
> }
> })
> 
> controller.B.onEvent(ControllerButtonEvent.Pressed, function() {
> sw.reset()
> })
> 
> game.onUpdate(function() {
> if (sw.isRunning) {
> sw.update()
> }
> })
> 
> ```
> 
> Feel free to run your project. You can mash on the buttons all you want, but nothing will seem to change. The functions in our class **are** getting called. However, because the functions are empty, nothing on the screen changes.

> **Recalling Blocks implementation**
>
> Think back again to the Blocks version. When the user pressed **A** , we called a function called `startTimer`. What happened in that function? What about `stopTimer`? And `resetTimer`?
> 
> If you’re comfortable in TypeScript and comfortable with the code from the Blocks implementation, then pause here and see if you can write the code for `reset()`, `update()`, `start()`, and `stop()` in the **Stopwatch** class.
> 
> If you’re not quite there yet, then that’s OK! Pause here for a moment anyway and reflect on the code that we wrote in Blocks. Once you’re comfortable with that code, return here. We will implement the `start()` function next.

> **Implementing start**
>
> Normally, I probably would write the `reset()` and `update()` functions first. There wouldn’t be any real change in the sprite, though, so let’s instead write the `start()` function.
> 
> Recall from the Blocks implementation that the `startTimer` function saved the current game time and then set the Boolean variable to **true**. Let’s do the same thing in our **Stopwatch** class.
> 
> _ **stopwatch.ts** _
> 
> ```typescript
> public start() : void
> {
> this.startTime = game.runtime()
> this.isRunning = true
> }
> 
> ```
> 
> Run your game in the simulator and press the **A** button. Nothing seems to happen. Why not?

> **Implementing update**
>
> Our text sprite stays at zero, even after the stopwatch has started. Why is that? Because we never change the text in the text sprite.
> 
> Remember that, in **main.ts** , we call the `update()` function in the main game loop if the stopwatch is running. That seems like a good place, then, to set the text of the sprite.
> 
> Think back again to our Blocks implementation. How did we figure out what text to display? We had to do a little bit of math, and then we did had to convert the value of that calculation to text (a **string** in TypeScript).
> 
> Can you come up with the code for the `update()` function? Give it a try if you like. Be sure to leave that call to the `super` version of the function. (Leave it as the last statement that runs before exiting the function.) When you’re ready, reveal the spoiler below to see the code.
> 
> _ **stopwatch.ts** _
> 
> ```typescript
> public update() : void
> {
> let time : number = this.accumulatedTime
> if (this.isRunning) {
> time += (game.runtime() - this.startTime) / 1000
> }
> this.text = time.toString()
> super.update()
> }
> 
> ```
> 
> Run your program and press **A** on the controller to start the clock. Now, we just need to figure out how to stop it!

> **Implementing stop**
>
> As before, think about how we implemented the `stopTimer` function in Blocks. You’re probably getting pretty good at writing TypeScript by now, so give it a try. See if you can write the `stop()` function for our **Stopwatch** class. Then, reveal the spoiler to see my code.
> 
> _ **stopwatch.ts** _
> 
> ```typescript
> public stop() : void
> {
> this.isRunning = false
> this.accumulatedTime += (game.runtime() - this.startTime) / 1000
> this.update()
> }
> 
> ```
> 
> Run your program. Pressing the **A** button on the controller should allow you to start and pause the stopwatch.

> **Implementing reset**
>
> The only thing left is to implement `reset()`. As before, give it a try on your own. Reveal the spoiler when you are ready!
> 
> _ **stopwatch.ts** _
> 
> ```typescript
> public reset() : void
> {
> this.isRunning = false
> this.accumulatedTime = 0
> this.update()
> }
> 
> ```
> 
> We now have a functional stopwatch in TypeScript!

# Extras

> **Additional functionality**
>
> Here are some ideas to improve our **Stopwatch** class. I implemented some of these ideas in my finished version, which you can find at the beginning of this post.
> 
> - You may have notice some long decimals as the stopwatch ran, especially if you start and stop the clock. Can you display the time rounded to the nearest tenth or hundredth?
> - After 60 seconds have passed, the timer continues to count in seconds. You may not be used to seeing a stopwatch with 85 seconds displayed. Can you display the time to include minutes, as well?
> - Do you have other ideas that would improve our stopwatch?

> **Full Stopwatch class diagram and PlantUML code**
>
> ![6](https://us1.discourse-cdn.com/flex020/uploads/makecode/original/2X/5/554d9ca93445cb60aef8ed3640e7dbbef3d0ef21.png)
> 
> I used PlantUML to create the class diagrams in this post. The code for the diagram is below. Visit the link below to view and edit the code at the PlantUML web site.
> 
> [Stopwatch class diagram at PlantUML web site](http://www.plantuml.com/plantuml/uml/VPDFQ_Cm3CRl-HG-9gI5zrnuHzbWh8SoM0ix5iTH4uF_15kc7Tk--voagPLrj2VhaVH8lzXTU-GEWrQPKDnxjaFRdJYAbdrcZ2sbVml6IDEiM6Mj0cvwbGiHT50SeTxw5JD1L-3wn62sbng8M0fhFBeWqBgyw8K6S8UnEI-eQ-d00uuLWyzqjDru2bqzDFM3ZjPfFapAzNM3Q1S7nMMpx-o2iuSpxZed4GQU4cDyhOfnrT1DZxD8y_EpDVW2iccH9YhhQd3liiRsLdwooZegTxokupGgsO1A6g0ELB-naCAQ5TjetW3x7tMbedeu_Fwu56x14jg27SdvJwn5nkAFWALwWfN414NQ2HRffr19lKKg9YPwqQK7tDA5ytQszrIpYNOvyPpq_lvdtsLAF0vK-Mc-gxXB6HVzD_M_ZbHt3Ohq3kaRFDEh_RW6iJRz-PRBhmVoUBDq75CNUGsc3bhz0000)
> 
> ```plantumlcode
> @startuml
> class Stopwatch {
> -isRunning: boolean
> -accumulatedMs: number
> -startTime: number
> +constructor()
> +getState(): boolean
> +reset()
> +start()
> +stop()
> +update()
> -formatTime(ms: number): string
> }
> 
> class TextSprite {
> +text: string
> +bg: number
> +fg: number
> +maxFontHeight: number
> +borderWidth: number
> +borderColor: number
> +padding: number
> +outlineWidth: number
> +outlineColor: number
> +icon: Image = null
> __
> +constructor(text: string, bg: number, fg: number, maxFontHeight: number,
> borderWidth: number, borderColor: number, padding: number,
> outlineWidth: number, outlineColor: number, icon: Image = null)
> __
> +update()
> +setMaxFontHeight(height: number)
> +setIcon(icon: Image)
> +setText(text: string)
> +setBorder(width: number, color: number, padding: number = 0)
> +setOutline(width: number, color: number)
> }
> 
> class Sprite {
> +x: number
> +y: number
> }
> 
> Stopwatch --|> TextSprite
> TextSprite --|> Sprite
> @enduml
> 
> ```
