JavaBasic syntax and simple programsIntroduction to Java

Scala Test

2 seconds read

We have already learned that classes have methods. Why don't we use the normal functions we used before? Do class methods have specific purposes? Let's learn more about class methods and find out the answers to these questions!

A method as a function

A class method is nothing more than a regular function. The difference is that this function is class-specific. Let's take a look at an example.

Let's imagine that we want to have a function that will display credit card details:

class CreditCard(val number: String)

def show(prefix: String, card: CreditCard): String = 
  prefix + s"Card(***${card.number.takeRight(4)})"

This function takes parameters and displays the information we need. From the point of view of logic, everything is correct, but let's see how you can turn this function into a CreditCard class method:

class CreditCard(val number: String):
  def show(prefix: String): String = prefix + s"Card(***${number.takeRight(4)})"

Here we put the function inside of the class, so it becomes a class method. As you can see, now we don't pass CreditCard to the function parameters: instead, we can use the number field as the value we want to output.

Our CreditCard class currently consists of only one field — the card number.

val card = CreditCard("12345678")
println(card.number)

This piece of code will print the credit card number to the console. But do we need this behavior? The card number is personal information, let's make sure that no one from the outside has direct access to it:

class CreditCard(private val number: String):
  def show(prefix: String): String = s"$prefix" + s"Card(***${number.takeRight(4)})"

Now that we've added a private access modifier, we can access the field within this class, as we did in the show function.

But now no one from the outside will be able to use this field. Let's see what the program would display in the very first example:

def show(prefix: String, card: CreditCard): String = 
  prefix + s"Card(***${card.number.takeRight(4)})"
Error: value number in class CreditCard cannot be accessed

Default parameters

Sometimes we want to use some default arguments. In this case, the user can either pass the parameter or not.

Let's look at the show example again:

class CreditCard(private val number: String):
  def show(prefix: String = ""): String = prefix + s"Card(***${number.takeRight(4)})"

Now we can define the prefix:

scala> println(creaditCard.show("INFO: "))
INFO: Card(***1234)

Alternatively, we leave it as default:

scala> println(creaditCard.show())
Card(***1234)

It's important to note that, for convenience, all default arguments of the method are carried to the end.

Since the parameters must be passed in the same order, it could be confusing which parameters we left to default and which we explicitly passed.

The showInfo method must be defined as follows:

def showInfo(
  name: String,
  surname: String,
  age: Int,
  homeAddress: String = "undefined",
  school: String = "undefined",
): String =
  s"""Information:  
     |Name: $name 
     |Surname: $surname 
     |Age: $age 
     |School number: $school 
     |Home Address: $homeAddress""".stripMargin

Here is a call using default arguments:

showInfo("Alice", "Brown", 20)

So, we can determine that the first 3 parameters were not passed by default.

Parameter names

Arguments can be passed in a different order if you specify the field names to which they need to be assigned.

class Rectangle(height: Int, width: Int)

val figure1 = Rectangle(height = 10, width = 15)
val figure2 = Rectangle(width = 15, height = 10)

In the example above figure1 and figure2 have the same height.

If your class or method has a large number of parameters, it's better to name the fields for readability when creating a class instance or calling a method:

class Person(name: String, surname: String, age: Int, schoolNumber: Int)

// could be confusing
val person1 = Person("Alice", "Brown", 20, 30)

// all parameters are clear
val person2 = Person(name = "Alice", surname = "Brown", age = 20, schoolNumber = 30)

Auxiliary constructors

We can also create additional constructors for our classes using a special method called this:

class Rectangle(height: Int, weight: Int) {

  // constructor for a rectangle that is a square
  def this(size: Int) = this(size, size)
}

But in actual development, this functionality is hardly ever used. Companion objects are used for such constructors instead. You will learn about them in the upcoming topics.

Conclusion

In this topic, you took a closer look at class methods. As you now know, class methods are almost the same as functions, but unlike them, they refer only to a class, that is, they are some of its functionality. We also learned what private fields and private methods are, got acquainted with default values, and learned how you can pass arguments in a specified order.

Now let's get down to the tasks to master this topic better in practice!

How did you like the theory?
Report a typo