1. 类的定义:最简形式
Scala 的类定义和 Java 类似,但语法更简洁。
Scala 示例:
scala复制代码
class Person {
var name: String = "" // 可变变量
val age: Int = 0 // 不可变变量(类似Java的final)
def sayHello(): Unit = {
println(s"Hello, I'm $name, $age years old.")
}
}
Java 对比:
java复制代码
public class Person {
private String name = "";
private final int age = 0;
public void sayHello() {
System.out.println("Hello, I'm " + name + ", " + age + " years old.");
}
}
关键点:
- Scala 中成员变量(字段)可以直接声明在类体中,不需要放在构造器中。
var
表示可变变量,val
表示不可变变量(类似 Java 的final
)。- 方法定义用
def
,返回值类型在参数后(如Unit
表示无返回值,类似 Java 的void
)。
2. 构造器:主构造器 vs 辅助构造器
Scala 的构造器分为主构造器和辅助构造器,这是与 Java 不同的重要特性。
(1) 主构造器(Primary Constructor)
主构造器是类定义的一部分,直接写在类名后面。
Scala 示例:
scala复制代码
class Person(var name: String, val age: Int) {
def sayHello(): Unit = {
println(s"Hello, I'm $name, $age years old.")
}
}
Java 对比:
java复制代码
public class Person {
private String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void sayHello() {
System.out.println("Hello, I'm " + name + ", " + age + " years old.");
}
}
关键点:
- 主构造器的参数直接写在类名后的括号中。
- 如果参数用
var
或val
修饰,会自动生成对应的公有字段(类似 Java 的 public 成员变量)。 - 如果参数不加
var
/val
,则参数仅作为构造器参数使用,不会成为类的字段。
(2) 辅助构造器(Auxiliary Constructor)
辅助构造器通过 def this(...)
定义,且必须调用主构造器。
Scala 示例:
scala复制代码
class Person(var name: String, val age: Int) {
// 辅助构造器1
def this(name: String) {
this(name, 0) // 必须调用主构造器
}
// 辅助构造器2
def this() {
this("Anonymous") // 调用辅助构造器1,最终仍调用主构造器
}
}
Java 对比:
java复制代码
public class Person {
private String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person(String name) {
this(name, 0);
}
public Person() {
this("Anonymous");
}
}
关键点:
- 辅助构造器必须首先调用主构造器(或另一个辅助构造器)。
- 主构造器是 Scala 类的唯一入口。
3. 继承:extends
关键字
Scala 的继承机制与 Java 类似,但方法覆盖必须用 override
关键字。
Scala 示例:
scala复制代码
class Animal {
def speak(): Unit = {
println("Animal speaks")
}
}
class Dog extends Animal {
override def speak(): Unit = {
println("Dog barks")
}
}
Java 对比:
java复制代码
public class Animal {
public void speak() {
System.out.println("Animal speaks");
}
}
public class Dog extends Animal {
@Override
public void speak() {
System.out.println("Dog barks");
}
}
关键点:
- 用
extends
继承父类。 - 覆盖方法必须加
override
关键字(Java 的@Override
是注解,Scala 的override
是强制语法)。
4. 抽象类:abstract
关键字
抽象类用于定义未实现的方法或字段,类似 Java 的抽象类。
Scala 示例:
scala复制代码
abstract class Shape {
def area(): Double // 抽象方法(无实现)
val color: String // 抽象字段
}
class Circle(radius: Double, override val color: String) extends Shape {
override def area(): Double = Math.PI * radius * radius
}
Java 对比:
java复制代码
public abstract class Shape {
public abstract double area();
public abstract String getColor();
}
public class Circle extends Shape {
private double radius;
private String color;
public Circle(double radius, String color) {
this.radius = radius;
this.color = color;
}
@Override
public double area() {
return Math.PI * radius * radius;
}
@Override
public String getColor() {
return color;
}
}
关键点:
- 抽象方法用
def
定义,无方法体。 - 抽象字段用
val
或var
声明,无初始值。 - 子类必须实现所有抽象成员。
5. 伴生对象:object
关键字
Scala 没有静态成员(static
),而是通过伴生对象实现类似功能。
Scala 示例:
scala复制代码
class Person(val name: String, val age: Int)
// 伴生对象(与类同名)
object Person {
def apply(name: String, age: Int): Person = new Person(name, age)
def apply(name: String): Person = new Person(name, 0)
}
// 使用伴生对象创建实例
val p1 = Person("Alice", 30) // 调用 apply 方法
val p2 = Person("Bob")
Java 对比:
java复制代码
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public static Person create(String name, int age) {
return new Person(name, age);
}
public static Person create(String name) {
return new Person(name, 0);
}
}
// 使用静态工厂方法
Person p1 = Person.create("Alice", 30);
Person p2 = Person.create("Bob");
关键点:
- 伴生对象与类同名,定义在同一个文件中。
- 通过
apply
方法实现类似构造器的调用语法。 - 伴生对象可以访问类的私有成员。
6. 特质(Trait):类似接口的增强版
Scala 的 trait
类似 Java 的接口,但支持方法实现和多重继承。
Scala 示例:
scala复制代码
trait Speaker {
def speak(): Unit // 抽象方法
def greet(): Unit = {
println("Hello!") // 具体方法
}
}
class Human extends Speaker {
override def speak(): Unit = {
println("Human speaks")
}
}
val h = new Human
h.speak() // 输出:Human speaks
h.greet() // 输出:Hello!
Java 对比(Java 8+):
java复制代码
public interface Speaker {
void speak();
default void greet() {
System.out.println("Hello!");
}
}
public class Human implements Speaker {
@Override
public void speak() {
System.out.println("Human speaks");
}
}
关键点:
- 特质可以包含抽象方法和具体方法。
- 类通过
with
关键字继承多个特质:scala复制代码
class Robot extends Speaker with Walker with Worker
- 解决多重继承冲突时,采用线性化规则(最后继承的特质优先级最高)。
7. Case 类:专为模式匹配优化的类
case class
是 Scala 中特殊的类,自动生成常用方法(如 equals
、hashCode
、toString
)。
Scala 示例:
scala复制代码
case class Point(x: Int, y: Int)
val p1 = Point(1, 2)
val p2 = Point(1, 2)
println(p1 == p2) // 输出 true(自动实现值比较)
Java 对比:
需要手动实现 equals
、hashCode
、toString
等方法。
关键点:
- 默认字段为
val
(不可变)。 - 自动生成伴生对象和
apply
方法。 - 支持模式匹配:
scala复制代码
def describe(p: Point): String = p match { case Point(0, 0) => "原点" case Point(x, 0) => s"X轴上的点($x, 0)" case _ => "其他点" }
总结:Scala vs Java 类设计的差异
特性 | Scala | Java |
---|---|---|
构造器 | 主构造器 + 辅助构造器 | 普通构造器 |
静态成员 | 通过伴生对象实现 | static 关键字 |
接口 | 特质(支持方法实现) | 接口(Java 8+ 支持默认方法) |
不可变类 | 用 case class 自动生成 |
需手动实现 |
多重继承 | 通过特质支持 | 不支持(接口允许多实现) |