Conteúdo do Curso
Android Development with Kotlin
Android Development with Kotlin
Classes and Objects
What is OOP?
Object-Oriented Programming (OOP) is a programming paradigm that organizes software design around data or objects rather than functions and logic.
An object is a self-contained entity that contains both data (attributes) and procedures (methods).
OOP helps structure code to be modular, reusable, and easier to maintain by representing real-world entities as objects in the program.
For a better understanding, let's go back to the previous chapter, where we stored employee data in separate variables.
With OOP, "Employee
" will be a separate class with fields like name
, salary
, and so on. These will be the attributes of the Employee
object. Instead of working with variables, we'll operate with the fields and methods of this object.
This approach is much easier and more intuitive, so let's dive into OOP in Kotlin!
Defining Classes and Creating Objects
In Kotlin, a class is a blueprint for creating objects. It defines the properties (attributes) and methods (functions) that the objects will have.
Let’s create an Employee
class that will represent the employee from the previous chapter:
Note
We can define a class using the
class
keyword.
Employee
class Employee(val name: String, val position: String, var salary: Int, var yearsOfExperience: Int) { // Methods and additional properties can be defined here }
Let’s break down what’s written above using an illustration:
Let’s talk more about the constructor. The primary constructor defines the fields that the class will have. Then, when creating an Employee
object, we need to provide the fields shown in the constructor, namely:
- We need to specify the
name
,position
,salary
, andyearsOfExperience
for each employee; - This needs to be provided for each
Employee
object, so we will be adding "new employees" to the code through objects.
Let's look at an example of creating an object in the main
function with field initialization. This is done using the following syntax:
val variableName = ClassName(property1, property2, ...)
Here’s how creating an employee named "John" would look:
Main
class Employee(val name: String, val position: String, var salary: Int, var yearsOfExperience: Int) { // Methods and additional properties can be defined here } fun main() { val john: Employee = Employee("John", "Developer", 3800, 4) println("Employee info: name: ${john.name}, position: ${john.position}, salary: ${john.salary}, years of experience: ${john.yearsOfExperience}") }
As you can see in the code above, we create the same class, but now in the main
function, we create an OBJECT of this class, which is stored in a variable named john
.
Note
We create the class separately from writing the function; we cannot create a class inside a function, but we can create a function inside a class.
We initialize the john
object with specific fields through the constructor and then display information about this employee.
However, if we have many employees, it would be inconvenient to display information about each one manually. Therefore, we will write a method that will be inside the class and can be called on any object of this class (e.g., john
).
This method will display information about the employee and will be named introduce
:
Main
class Employee(val name: String, val position: String, var salary: Int, var yearsOfExperience: Int) { fun introduce() { println("Employee info: name: $name, position: $position, salary: $salary, years of experience: $yearsOfExperience") } } fun main() { val john: Employee = Employee("John", "Developer", 3800, 4) val alice: Employee = Employee("Alice", "Marketer", 2300, 2) john.introduce() alice.introduce() }
You might be wondering why we wrote a function inside the Employee
class but referred to it as a method. The answer is quite simple: in the context of OOP, functions that belong to specific classes are commonly called methods. So, introduce
is a method of the Employee
class that can be called on any object of that class. This is exactly what we do in the main
function. We create two objects of the Employee
class and call the introduce()
method on each of them.
When writing a method, we can access fields (properties) directly. Alternatively, we can use the this
keyword, which represents the current object to which the method is applied.
In the case of using the this
keyword, the introduce
method would look like this:
Main
fun introduce() { println("Employee info: name: ${this.name}, position: ${this.position}, salary: ${this.salary}, years of experience: ${this.yearsOfExperience}") }
In this case, this
will refer to the object on which the method is being called. For example, when calling this method on the john
object, the this
keyword will refer to the john
object and so on.
Secondary Constructor:
Besides methods, we can also do without the primary constructor by specifying the fields and constructor manually.
Here’s how you can do it:
Employee
class Employee { val name: String val position: String var salary: Int var yearsOfExperience: Int constructor(name: String, position: String, salary: Int, yearsOfExperience: Int) { this.name = name this.position = position this.salary = salary this.yearsOfExperience = yearsOfExperience } fun introduce() { println("Employee info: name: ${this.name}, position: ${this.position}, salary: ${this.salary}, years of experience: ${this.yearsOfExperience}") } }
As you can see, here we explicitly specify the fields used in the class and the constructor that initializes these fields using the this
keyword.
Secondary constructors are defined inside the class body using the constructor
keyword. They are useful when you need additional initialization logic.
You can also have both primary and secondary constructors in a class. Secondary constructors can call the primary constructor using the this
keyword:
Employee
class Employee(val name: String, val position: String, var salary: Int, var yearsOfExperience: Int) { var department: String? = null constructor(name: String, position: String, salary: Int, yearsOfExperience: Int, department: String?) : this(name, position, salary, yearsOfExperience) { this.department = department } fun introduce() { println("Employee info: name: ${this.name}, position: ${this.position}, salary: ${this.salary}, years of experience: ${this.yearsOfExperience}") } }
Here, we added a new optional field, department
, which is declared in the secondary constructor. This might seem complex right now, but don't worry— we won't use it immediately, and when we do, it will become very straightforward for you!
Summary
- Classes are blueprints for creating objects with properties and methods;
- Objects are instances of classes;
- Properties represent the state or data of an object, while methods define the behavior;
- Primary constructors initialize properties directly in the class header, while secondary constructors offer additional ways to initialize objects.
Obrigado pelo seu feedback!