0% found this document useful (0 votes)
12 views

Lesson 3 Classes and objects (1)

Uploaded by

Dương Khánh
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views

Lesson 3 Classes and objects (1)

Uploaded by

Dương Khánh
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 56

In this lesson, we’re going to be talking about object oriented programming concepts

in Kotlin including classes and inheritance. You may already know about object
oriented programming from other languages, so some of these concepts may be
familiar to you. We’ll also cover unique aspects of the Kotlin language like extension
functions and special classes, which make it easier for you to write your code as a
developer.
Classes are blueprints for objects. Each class can contain properties and methods to
operate on the object. You can have different classes for different types of objects. In
this example, we have a class (or blueprint) for a House. From the blueprint, we can
create actual House object instances. Each House object instance has all the fields
and methods listed in the definition of the class.

The definition of a class is written in a Kotlin file.


The House class contains a blueprint of what goes into a House. It has properties like
color (which is a String), number of windows (an Int), and whether or not the house is
for sale (a Boolean).

The House class also contains methods like updating the house color or putting the
house on sale.

We use the class to create object instances of the class. On the right are 3 different
House object instances that have different attributes. They have different colors and
one is even for sale.
Transition: 1 click

Let’s look at the code for how to define and use a class. To define a class, use the
keyword class followed by the name of the class, which is House in this case. Then
use curly braces around the class body. Inside this class definition, we see 3
properties and 1 function.

Use the syntax on the right to create a new object instance of the House class. Use
the class name followed by parentheses. In other languages, you might use the “new”
keyword to create new object instances, but in Kotlin there is no “new” keyword.
Another reason why Kotlin is a more concise language!

Resource:
● Classes and Inheritance
Transition: 1 click

A class declaration consists of the class name, the class header (specifying its type
parameters, the primary constructor, etc.) and the class body, surrounded by curly
braces. Both the header and the body are optional; if the class has no body, curly
braces can be omitted, as shown in the example above..

A class in Kotlin can have a primary constructor and one or more secondary
constructors. The primary constructor is part of the class header: it appears after the
class name (and optional type parameters).
These are different examples of how you can define constructors with or without
parameters.

The constructor for class A has no parameters.

The constructor for class B has 1 input parameter: x which is an Int. Because the
parameter is not marked as a var or val, the variable x does not exist outside the
scope of the constructor. Hence, if we create an object instance called bb, and we try
to call the property x on it, we will get a compiler error. The property x does not exist
on the object.

In the third case, we have a constructor for class C with 1 input parameter: a val
called y. If you create an object instance called cc, you can access the property y
which has the value of 42 in this case.

To summarize, you can define the properties directly within the constructor, using var
or val (as seen in the third example).
Transition: 1 click

Similar to how we learned about default parameters in functions in Lesson 2, we can


have default parameters for constructors.

That means, parameters can have default values and don’t need to be specified when
the object is initialized. If no default value is provided, then the parameter is required
in the constructor. You can mix default and required parameters in a constructor.

For this class declaration of Box, width and height have default values. No default
value is provided for length, so specifying the length is required when creating a
new Box object. Because these three parameters are marked with val, we know
these are member variables of the Box class.

Underneath the class declaration, we have three examples of how you would create
new Box objects. Even though they specify the constructor arguments in different
ways, the three Box objects are equivalent.
Transition: 1 click

For all examples we’ve seen so far, the constructor is within the class header. This is
called the primary constructor.

This syntax makes Kotlin more concise when it comes to defining classes.

Technically, the first code snippet is equivalent to the second one (which is more
verbose). The second code snippet looks more like how you would define a class in
another language, where the constructor is explicitly defined by itself.

But in Kotlin, write your code according to the first code snippet. Notice the init block?
Let's take a look at that.
In Kotlin, you can’t put any code inside a primary constructor, so put any initialization
code in an init block - also known as an initializer block. You can have more
than 1 init block in your class definition. The blocks just get executed in the order
that they appear in the code. These init blocks essentially become the body of the
primary constructor.
In this example, we have a Square class where the primary constructor has 1 input
parameter: the side length as an Int. We want to do some work in the constructor of
the Square class, so we setup an init block. Within it, we have a println statement.

Outside of the class definition, we can create a new Square object instance with a
side of 10. As soon as it is initialized, the init block is executed and the print
statement gets printed to the output.
What if we need multiple constructors? In addition to the primary constructor, a class
can have one or more secondary constructors. Use the constructor keyword to
declare them.

A secondary constructor must call the primary constructor using the this keyword.
Or it must call another secondary constructor that calls the primary constructor.

Warning: Using multiple constructors leads to more code paths and issues with
testing. Before writing a secondary constructor, consider whether a factory function
would work instead, to keep the class definition clean.

Resource:
● Classes and Inheritance
In the Circle class, we have a primary constructor (that takes a double radius value
as input) and 2 secondary constructors.

To define a secondary constructor, start with the constructor keyword followed by


parameters, a colon, and a call to the default constructor with this (which takes
the radius as input). For classes with multiple constructors like this one, the init
block runs before any code in the secondary constructor. Hence, the println
statement will be executed before any of the code within the secondary constructors.
Define properties in a class using val or var, as you learned earlier. Access these
properties by using the object name followed by "." and the property name. If the
property was declared a var, then you can also set the property using dot notation.
You can’t modify an object’s property if it was declared a val. You will get an error
that the val cannot be reassigned.
In this example, we create a Person class with a name property. In the main function,
create a Person object instance. Then access and set its name property with dot
notation. Because name is a var, we can change the name property with the setter. If
it was declared with a val in the constructor of the Person class, we would not be
able to change it.
If you don’t want the default get/set behavior for a property, then you can
customize your own getter or setter for a property. Again, you can only override
set() if the property was defined as var.

This is what the general format would look like for declaring a mutable property in a
class. Declare it with var and then the property name. Use a colon followed by the
data type. Then set it equal to an initial value (this can be an expression). Then you
can optionally override the get() or set() function for the property.

Resource:
● Properties
Let’s look at an example in the Person class. Define a variable called fullName,
with a custom getter function that combines the first and last name into a single
String. You can access fullName like a property (using person.fullName in the
example), and the get() function gets executed on the fly.
For that same property, you can also define a custom setter function that takes in a
single string and splits it into first name and last name components. You can set
fullName like a property, using person.fullName = <the new name>, which
is “Jane Smith” in the example. The underlying set() function would get called.
In addition to constructors and properties, classes can also have member functions.
Declare functions according to the rules we discussed in "Functions" in Lesson 2.

Resource:
● Member Functions
Classes are very useful, and you can receive even more benefit from them by
inheriting properties and behavior from other classes. Let’s talk about inheritance in
Kotlin next.
Inheriting the properties and capabilities from parent class to child class is called
Inheritance.

Kotlin has a single-parent class inheritance structure, should you need multiple class
features to be inherited in your class, consider using Interfaces.

Resource:
● Inheritance
Transition: 1 click

We defined an interface called Shape that has a single function


computeArea(). Any class that implements that interface must override the function
as shown in the example with Circle.

This is how you would create a new Circle object instance, call its
computeArea() method, and prints the result to the output.
In Kotlin, classes are final by default, meaning that they cannot be inherited. To make
a class inheritable, you need to use the open keyword, as explained on the next
slide.

Resource:
● Inheritance
By using the open keyword to declare class C, we can successfully define class D as
a subclass of C.

Because superclasses need to have one of their constructors used, even a no-arg
one, you can easily determine which are classes and which are interfaces by the lack
of parentheses.
Abstract classes do not need to be marked with the open keyword because it’s
implied that they will be subclassed.
Abstract classes share some commonality with interfaces: that is, you can’t directly
instantiate an abstract class, and there can be functions that you must override in
your subclasses. They differ from interfaces in that abstract classes can provide
implementations of functions and properties. For interfaces, all declared properties
are by default abstract and must be provided by the subclasses. In our Pizza
example, we inherited the consume() function, but had to override the properties
kcal and name.

Resource:

● Abstract classes
● Classes and Inheritance
Resource:
● Data Classes
The data class version of Player displays the member variables without needing to
implement a toString() method explicitly.
Resource:
● Collections
Note that the first, second, and third values can be of different types, as shown in the
example for bookAuthorYear.
Transition: 1 click
In other languages, you’d use some for of getInstance and making things
private.
Members of companion objects may look like static members from other languages,
but they are part of real object instances. For example, you can use companion
objects when defining constants in a class, when you want it closely coupled to the
class, and when you only need one instance of it.

Resource:
● Companion Objects
Note: Companion objects can implement an interface and are real objects.

Resource:
● Companion Objects
The defining line of when you should split into a new file is somewhat a matter of
personal preference.
In program source code, packages are used to group related program elements such
as classes, variables, and functions. In Kotlin, these elements are declared in files
with a package declaration at the top of the file. To use elements that are part of a
package in another package, you import the package. The package name customarily
contains only lowercase letters (no underscores) and separating dots and has to be
globally unique. For example: package org.example.game.

At time of writing, package private has not been implemented in Kotlin, so the
package doesn’t limit visibility as it would in other languages.
If the Moped class and its subclasses aren’t too long, it’s fine to put them in the same
class. Same with the Car and its descendants.
Classes, objects, interfaces, constructors, functions, properties, and their setters can
have visibility modifiers

Use visibility modifiers to limit the API you expose.

In other languages, you have to explicitly specify “public”. But in Kotlin, if you don’t
specify a visibility modifier, it is public by default.

Resource:
● Visibility Modifiers

You might also like