Scala Tutorial
Basics
Control Statements
OOP Concepts
Parameterized - Type
Exceptions
Scala Annotation
Methods
String
Scala Packages
Scala Trait
Collections
Scala Options
Miscellaneous Topics
In Scala, getters and setters (commonly referred to as accessors and mutators) are automatically generated for class fields. However, you can override or customize these generated methods. Let's take a deeper dive into this topic.
When you declare a var
or a val
in a class, Scala automatically generates a getter for it. If it's a var
, a setter is also generated. You can override the default getter by defining a method with the same name as the field.
class Person { private var _name = "Default" def name: String = { println("Getting name") _name } } val person = new Person println(person.name) // Getting name // Default
In the example above, accessing name
will now print "Getting name" before returning the value.
To override the default setter for a var
, you can define a method with the name fieldName_=
.
class Person { private var _name = "Default" def name: String = _name def name_=(newName: String): Unit = { println(s"Setting name to $newName") _name = newName } } val person = new Person person.name = "John" // Setting name to John println(person.name) // John
In this example, assigning a new value to name
prints a message.
By overriding getters and setters, you can introduce additional logic, such as validation or notification mechanisms.
class Circle { private var _radius: Double = 1.0 def radius: Double = _radius def radius_=(r: Double): Unit = { if (r >= 0) _radius = r else println("Radius cannot be negative!") } } val circle = new Circle circle.radius = -5 // Radius cannot be negative!
Here, we ensure that the circle's radius can never be set to a negative value.
@BeanProperty
for Java InteroperabilityIf you're interfacing with Java code that expects traditional "get" and "set" prefixes for accessor and mutator methods, you can use the @BeanProperty
annotation:
import scala.beans.BeanProperty class Person { @BeanProperty var name: String = _ } val person = new Person person.setName("John") println(person.getName)
This generates both the Scala-style and Java-style getter and setter methods.
In conclusion, Scala offers a neat way to override default accessors and mutators, allowing developers to introduce custom behaviors while keeping the code concise and expressive.
Description: Customizing getters and setters allows for fine-grained control over property access and mutation.
Overriding Default Accessors in Scala:
class MyClass(private var _value: Int) { def value: Int = { // Custom logic for getter _value + 10 } }
Modifying Default Mutators in Scala:
class MyClass(private var _value: Int) { def value_=(newValue: Int): Unit = { // Custom logic for setter _value = newValue * 2 } }
Advanced Property Access in Scala:
class MyClass(private var _value: Int) { def value: Int = { // Custom logic for getter _value + 10 } def value_=(newValue: Int): Unit = { // Custom logic for setter _value = newValue * 2 } }
Using 'override' Keyword for Accessors in Scala:
class MySubclass extends MyClass(5) { override def value: Int = { // Custom logic in subclass getter super.value * 2 } }
Changing Visibility of Accessors and Mutators in Scala:
class MyClass(private var _value: Int) { private var _secret: String = "hidden" def value: Int = _value private def secret: String = _secret }
Overriding Accessors and Mutators in Scala Traits:
trait Loggable { var logMessage: String = "Default Log" def log(): Unit = println(logMessage) } class MyClass extends Loggable { override def logMessage: String = "Custom Log Message" }
Encapsulation in Scala with Custom Accessors and Mutators:
class BankAccount(private var _balance: Double) { def balance: Double = _balance def deposit(amount: Double): Unit = { // Custom logic for deposit _balance += amount } def withdraw(amount: Double): Unit = { // Custom logic for withdrawal if (_balance >= amount) _balance -= amount } }