Chapter 5 Object oriented programming

Tram Ho

Chapter 5 Object oriented programming

I was first introduced to object-oriented programming in college where I had a brief introduction to C ++. C ++ is still relatively new at this point in time. In fact, the first version of the language was only published three years before I was introduced to it. The object-oriented programming model that was formed from the functional programming model I learned in the past at that time seemed quite overwhelming. I have even been introduced to that of object-oriented programming with c ++. I really didn’t develop anything important until I learned java later.

In this chapter, you will learn the following:

  • Swift can be used as an object-oriented programming language
  • How we develop an API in an object-oriented way
  • What are the benefits of object oriented design
  • What is the disadvantage of object oriented programming

While this book is about protocol-oriented programming, we really need to discuss how Swift can be used as an object-oriented programming language before learning how it can be used as a language-oriented language. protocol. Having an understanding of object-oriented programming will help us understand protocol-oriented programming and give us some perspective on the problems of protocol-oriented programming designed to deal with.

What is object oriented programming?

Object Oriented Programming is a philosophical design. Writing applications with an object-oriented programming language is fundamentally different from writing applications with old procedural languages ​​like C and pascal. A procedural language uses a set of statements to tell what a computer does step-by-step by relying on procedures (functions) or streams. However, an object-oriented programming language is all object-oriented. This may seem pretty obvious by name, but basically, when we think about object oriented programming we need to think about object.

An object is a data structure that contains information about the object’s properties in the form of properties, and actions performed by or to the object in terms of methods. Objects can be seen as objects and in the English language they are seen as nouns. These objects can be real-world objects or virtual objects. If you look around you will see many real-world objects and virtualize them that can be re-modeled by object-oriented with properties and actions.

As I am writing this chapter, I look around and see many trees, grass, my dog ​​and the fence in my yard. All of these can be modeled with attributes and actions.

I can also think about one of those energy drinks. That energy drink is Jolt Cola. I’m not sure how many people remember Jolt. but I wouldn’t be able to pass college without it. A Jolt can can be modeled as an object with properties (volume, caffeince content, temperature, size) and action (drink, change temperature).

We can keep many cans of Jolt in the refrigerator to keep them cold. The closet can also be modeled as an object because it has properties (temperature, multiple Jolt cans, and maximum number of cans) and actions (add, take out cans).

It is fine to define the properties and actions of an object, but we also need to understand how the object interacts. As the example above, when we put a can of Jolt in the refrigerator with some ice cubes, the Cans will start to get colder, however if there are no ice cubes in the refrigerator the can remains at room temperature. Understanding the interactions is crucial to accurate object design.

With a computer application we cannot create an object without a blueprint that tells the application what properties and actions to expect from the object. In most object-oriented languages, blueprints take the form of a class. A class is a structure that allows us to encapsulate the properties and actions of an object into a single modeled entity we use to represent in our code.

We use constructors inside of our classes to create class instances, we usually use constructors to set values ​​for object properties, or to execute any other constructor. your class needs. One more thing we create an instance of a class, we can use it in our code.

It is important to understand that classes are the framework of object oriented programming. If we don’t have a class and an object is created from that class we don’t have object oriented programming. It is equally important that the class is the reference type and it can inherit or create subclasses.

All these explanations in object oriented programming are fine. But nothing better demonstrates this concept than code. Before we can get started to code, we’ll need to define a few requirements. In this chapter, we will show how we can design the type of vehicle for a video game by object-oriented. In the next chapter we will show how we can design like these classes but by protocol oriented. Let’s see the requirements for the mode of transportation

When we develop applications, we often need to have a set of requirements we need to work with. My project example is in this chapter and it will be different in the next.

  • We have 3 types of terrain for vehicles: sea, land, sky. A vehicle can make 1 member of many types of terrain.
  • Vehicles can move or attack when they are on a square matching whatever type of terrain they belong to.
  • Vehicles will not be able to move or attack on a square that it does not match any vehicle it belongs to.
  • When a vehicle scores 0, it will be deemed incapacitated. We will need to keep all possible means in an array we will loop in

We’re going to demonstrate the design with only a few vehicles but we know that the number of vehicle types will grow with the growth of the game. In this chapter we are not going to implement a lot of logic for many types of vehicles because we focus on design and not much code to make the move into attack.

Let’s begin to design object oriented vehicles

Swift provides full support for object-oriented application development. Since swift 2. I have seen Swift as an object-oriented language like java and c #. In this section we will design vehicle types by object-oriented and let’s take a look at the pros and cons of this design.

Before we look at the code, let’s create a basic diagram to show how we will design the layered structure for object oriented design. In object oriented design we use class structure to group classes with similar relationships. Because Swift is a single-inheritance language. A class can only have one super class and inherit from that superclass. The base class in a subclass is one that has no superclass.

I usually start with a basic diagram, it’s simple to show classes without their details. This gives me a glimpse of the layered structure in my mind.

Here’s a graph showing we have a base class, Vehicle. With 5 subclasses named Tank, Amphibious, Submarine, Jet, Transformer. With a subclass model, each subclass will inherit all the properties and methods of the parent class, so any common code and properties can be executed in Vehicle and all subclasses will inherit. it.

We can think that with the 3 types of terrain (ground, air, sea) in our request, we would want to create a larger layered structure where the middle layer will contain but the superclass is separated. left for the ground, the sky, the sea. This allows us to separate code for each type into their superclass, but not with requests. The reason for this inability is that any type of vehicle can be a member of many types of terrain and with a single inheritance language like swift, each class can have only one parent class. This means if we create separate superclasses for each terrain type then. Amphibious classes can be subclasses of terrestrial or marine terrain, but not both.

Because swift is a single inheritance, and we can have only one parent class for all vehicle classes, the Superclass. This will need to contain code required for requirements for all 3 types of terrain. Having a single superclass here is one of the downsides of object-oriented design because the superclass can get too big.

We’ll begin to model object-oriented design by creating the TerrainType enumeration that will be used to define different vehicle types, attacks, and movements. Enumeration TerrianType looks like this:

Now let’s see how we will define the Vehicle superclass and the attributes in the class

We start the Vehicle type by defining seven attributes. The first 3 attributes are arrays of type TerrainType. These arrays hold traces of vehicleTypes, vehicleAttackTypes attacks, and vehicleMovementTypes.

The three attributes (landAttackRange, seaAttackRange, airAttackRange) will contain vehicle attacks for each type of terrain. If the attack range is less than 0 it means we can’t perform that type of attack. Finally, there are properties for storing the vehicle’s scores.

Refer properties as fileprivate because we want to distinguish them from subclasses. However, we do not want the external parts to change them. This level of access was introduced in Swift 3, and allows access to properties and methods from anywhere within the file in which the element is defined. For this to work, the subclass needs to be defined in the same physical file as the parent class. This is not a solution because this file can be very large. However, in object oriented design it is the best option we have to prevent properties that can be changed by entities of other data types. If we find that we have more than 5 media types we can change the level of access to internal so we can put the execution of the media in separate file.

Because the properties are marked as fileprivate we need to create some data retrieval method to get the values ​​of the properties. We’ll also create methods to see what type of terrain a vehicle can attack and move. Let’s see the following methods:

The isVehicleType method takes a parameter of type TerrainType and it returns true if the vehicleType array contains that type of terrain. This will allow external code to see what kind of data it is. The next two methods also accept a terrain type and return true if the vehicleAttackTypes or vehicleMovementTypes contains those types of terrain. These methods will be used to test whether a vehicle can move or attack from some type of terrain. The next six functions define ways to attack or move from vehicle terrain types. The next 2 functions will be used to calculate the reduction of the score when the vehicle takes one shot and returns the remaining score. The last method will be used to determine if the vehicle is still alive or not. There are some issues we can immediately see with this design. Let’s take a look before we move on.

One big design issue we talked about before. If we want to use fileprivate access which will prevent direct access to properties then all the subclasses need are in the same physical file as the Vehicle parent. the problem is that the vehicle class might be too big, we might not want them to be in the same file. To avoid this we can set the access level for properties to be internal, but it does not prevent these properties from being altered by other entities of type. This is the advantage of object oriented design because we do not want the outer types to have direct access to the properties.

The other problem with object-oriented design is that we need to provide methods that will allow the vehicle to attack and move for each different type of terrain, although most vehicles will not be able to attack and move. Transfers on all types of terrain. Although there is no code in the implementation of that method, the external code can still invoke the move and attack method. For example, although the submarine type is the sea type, the outside can still call the movement and attack function on land and in the air.

This is a big problem with an object-oriented programming language that inherits a single parent class like Swift. With the superclass as big as our vehicle type, it’s very easy to make an error and throw out a kind of function that shouldn’t or should not have. For example, it would be very easy to set the airAttackRange property for the submarine type and give it the ability to attack in the air, while the submarine cannot. (note) In this example we’re just defining a very small set of features required for our Vehicle type in a video game. Imagine how big the vehicle class would be if all the vehicles were executed.

Let’s see how we will subclass Vehicle by creating Tank, Amphibious, Transformer classes. We will start with the Tank class.

The tank class is a subclass of the Vehicle class, and we begin this class by overriding the default constructor. During the initialization we set some inheritance properties. Notice that we add the land values ​​to vehicleTypes, vehicleAttackTypes and vehicleMovementTypes. This indicates that the Tank type is a land vehicle that can attack and move on land.

Using arrays to keep track of the Vehicle class is a mobile, off-attack type of terrain is a problem in object-oriented design. Even most programmers get it wrong in these arrays resulting in unexpected behavior.

In the Tank class, we also override the doLandAttack () and doLandMovement () methods from the parent class because the Tank class inherits the vehicle. We do not override other methods such as attacking and moving from the Vehicle parent class because Tanks should not be able to travel and attack underwater or in the air. Although we don’t override these methods, they are still part of the Tank class. Because they are inherited from the parent class, there is no way to prevent outside code from calling those methods.

Now let’s take a look at the Amphibious and Transformer layers. These classes are quite similar to the Tank class, except that they can move and attack on a variety of terrain. We’ll see Amphibious first. This class can move and attack both on land and at sea.

The Amphibious class is very similar to the Tank class we have seen. The difference between the two is that the Tank type is defined only for the land topography while the amphibious is defined for both land and sea. So it has the land and sea type, we override the method of attack and travel on land as well as the method of attack and travel on the sea. We also add both land and sea values ​​to the vehicleTypes, vehicleAttackTypes, and vehicleMovementTypes arrays.

Now let’s take a look at the Transformer layer. This class is capable of moving and attacking on all 3 types of terrain.

With the Transformer class we override all the movement and attack methods from the Vehicle superclass, so the Transformer is capable of traveling and attacking on all three types of terrain. We also add three types of terrain to vehicleTypes, vehicleAttackTypes, and vehicleMovementTypes.

Now that they’ve made the Vehicle types, let’s see how we use them. One key requirement is that it can store instances of all Vehicle types in a single array. This will give us the ability to iterate over all active vehicles and perform any action if needed. To do this we use polymorphism (multiple inheritance).

Polymorphism (roughly translated as polymorphism)

A combined Greek word for poly (many) morph (shape). In computer science, we use pictograms when we want to use a single interface to represent multiple types of data in our code. Polymorphism gives us the ability to interact with multiple data types that unite the same interface. With object oriented programming languages, we can achieve polymorphism in subclasses where we interact with other classes using the same interface provided by the parent class.

Let’s see how we use polymorphism to hold all the different entities of the type of vehicle in a single array and interact with them. Since all vehicle types are subclasses of the Vehicle parent class, we can create an array of vehicle types and store instances of any type that are children of the Vehicle parent class.

We can now iterate through each entity in the array and interact with each one through the interface represented by the Vehicle type. The following code demonstrates

In this code we have iterated over the vehicle and used the isVehicleType (type) method to determine if the vehicle exists and call the appropriate transport and attack method for that vehicle. Note that we don’t use an if -else or switch case because each vehicle type can be a member of more than one type of data type we want to validate, even if that vehicle matches the previous one. .

If you want to filter the results and return only flying vehicles we will use the where statement with the for loop demonstrated in the following code.

This piece of code only executes the attack and moves if the isVehicleType (type) method returns true for type air.

This design works quite well, but as we can see in Chapter 6, Design-oriented protocol in Swift, we can solve many of the problems presented here by that design. Let’s review the shortcomings of object-oriented design so we can see how the protocol addresses them in the next chapter.

Problems with object oriented design

The two visible problems of object-oriented design are directly related to each other, and are the cause of Swift as a single inheritance language. Remember that a single inheritance language is a language that limits a class to only 1 superclass.

An object-oriented design with a single inherited language like swift could lead to the bloat of the superclass because we need to add the necessary features that are only needed for some subclasses. This leads to a second problem related to swift, where inherited features are not needed.

In our design we have to add features to the three types of terrain because the vehicle can move and attack on any type of terrain. There are these extra features that can lead to errors in our code if not careful. It can lead to crashes like the following example:

Looking at this code, we can easily see that vehicleMovementTypes array contains type sea and land type but it can easily generate error here.

Another problem with object-oriented design is that we cannot create constants in the parent class that can be set by the subclass. In our design, there are some properties we want to set in the subclass’s constructor and then never change. It would be ideal if we create constants, but this constant is defined in a class and cannot be set in its subclass.

The last problem we see is the inability to set properties or methods that can be accessed by subclasses. To solve this problem we use fileprivate to control, this means that the code defined in the same physical file can access those properties, however this workaround is not It’s a good idea because we don’t want to put all the subclasses of that type in the same file as the parent. If we put subclasses in separate files we might have to set the access level to internal, however this doesn’t prevent other data types in the project from altering them.

Summary. In this chapter we see how to design the vehicles for a video game by object-oriented. We also see how to use polymorphism with subclass structure. There are several problems with this object-oriented design, and its biggest drawback is directly related to Swift, which is the single inheritance language.

In the next chapter we’ll see how we can design the same vehicle type by driving the protocol and see how it solves the problems we see in object oriented design.

See you in the next chapter

Share the news now

Source : Viblo