Problem overview
A class bundles some values with the questions you can ask about them. Here the values are a rectangle's width and height, and the questions are its area, its perimeter and whether it is a square. You write the class Rectangle; the lesson's tests create several rectangles and ask each one the three questions.
Each object keeps its own sizes. A Rectangle(3, 4) has area 12, perimeter 14 and is not a square. A Rectangle(5, 5) has area 25, perimeter 20 and is a square. A rectangle that is 2 wide and 10 high and one that is 10 wide and 2 high both have area 20 and perimeter 24: turning a rectangle on its side changes neither.
How the class is built
The class header already declares the two sizes: class Rectangle(val width: Int, val height: Int). Writing val inside the parentheses does two jobs at once. The two names are the constructor's parameters, and they also become properties of every object. You don't write a separate field or an assignment. Inside any method, width and height mean the properties of the object the method was called on.
Each method needs only those two numbers, so each one takes constant time.
Step by step
- area. A 3 by 4 rectangle is 3 rows of 4 unit squares, so the area is width times height.
- perimeter. Walking around the rectangle you pass each side once: width, height, width, height. That is
2 * (width + height). The parentheses make the addition happen first. - isSquare. A comparison with
==is already aBoolean, true exactly when the two sizes are equal. Noifis needed.
The solution in Kotlin
class Rectangle(val width: Int, val height: Int) {
fun area(): Int {
return width * height
}
fun perimeter(): Int {
return 2 * (width + height)
}
fun isSquare(): Boolean {
return width == height
}
}
Two Kotlin details are worth knowing here:
width == heightcompares values. In Kotlin==callsequals, and forIntthat means the numbers are equal. (===is the one that compares references.)Intis a 32-bit number. The lesson keeps both sizes at or below 10,000, so even the largest perimeter, 40,000, and the largest area, 100,000,000, fit comfortably.
Using the class
You create an object by calling the class name like a function, with no new. Then you call the methods with a dot:
fun main() {
val a = Rectangle(3, 4)
println("${a.area()} ${a.perimeter()} ${a.isSquare()}")
val b = Rectangle(5, 5)
println("${b.area()} ${b.perimeter()} ${b.isSquare()}")
val c = Rectangle(2, 10)
val d = Rectangle(10, 2)
println("${c.area()} ${c.perimeter()} ${d.area()} ${d.perimeter()}")
}
It prints:
12 14 false
25 20 true
20 24 20 24
Kotlin prints booleans as true and false; the lesson's tests show them as True and False, so don't worry about that spelling in your own code.
Common mistakes
- Forgetting the parentheses in the perimeter.
2 * width + heightdoubles only the width. The height is then added only once, so the result is wrong for almost every rectangle. - Writing
valorvaragain in the body. The header already created the properties. Declaring new ones inside a method would make local variables that hide them. - Using an
ifforisSquare.if (width == height) return true else return falseworks, butreturn width == heightsays the same thing directly. - Calling a method without parentheses.
a.areais not a call. Writea.area().
