Python to Scala OOP Translation
Basic Classes
# Python
class Person:
def __init__(self, name: str, age: int):
self.name = name
self.age = age
def greet(self) -> str:
return f"Hello, I'm {self.name}"
// Scala
class Person(val name: String, val age: Int) {
def greet: String = s"Hello, I'm $name"
}
// Usage
val person = new Person("Alice", 30) // 'new' required for class
Data Classes → Case Classes
# Python
from dataclasses import dataclass
@dataclass
class Point:
x: float
y: float
@dataclass(frozen=True)
class ImmutablePoint:
x: float
y: float
// Scala - case class is idiomatic
case class Point(x: Double, y: Double)
// Case classes are immutable by default
// They auto-generate: equals, hashCode, toString, copy, apply
// Usage
val p = Point(1.0, 2.0) // No 'new' needed for case class
val p2 = p.copy(x = 3.0) // Creates new instance with x changed
Properties
# Python
class Circle:
def __init__(self, radius: float):
self._radius = radius
@property
def radius(self) -> float:
return self._radius
@radius.setter
def radius(self, value: float):
if value < 0:
raise ValueError("Radius must be non-negative")
self._radius = value
@property
def area(self) -> float:
return 3.14159 * self._radius ** 2
// Scala
class Circle(private var _radius: Double) {
require(_radius >= 0, "Radius must be non-negative")
def radius: Double = _radius
def radius_=(value: Double): Unit = {
require(value >= 0, "Radius must be non-negative")
_radius = value
}
def area: Double = math.Pi * _radius * _radius
}
// Idiomatic Scala: prefer immutable case class
case class Circle(radius: Double) {
require(radius >= 0, "Radius must be non-negative")
def area: Double = math.Pi * radius * radius
}
Inheritance
# Python
class Animal:
def __init__(self, name: str):
self.name = name
def speak(self) -> str:
raise NotImplementedError
class Dog(Animal):
def speak(self) -> str:
return f"{self.name} says woof!"
class Cat(Animal):
def speak(self) -> str:
return f"{self.name} says meow!"