Scala 类相关
终于来到面向对象的地方了,虽说函数式编程是 Scala 的特性,让人们觉得 Scala 是更好的 Java。但是在架构层面上一直提倡着:小处用函数式编程,大处用面向对象编程。
从这篇笔记开始,会记录类的相关内容。由于类相关的内容比较多,我可能会整理几篇文章来写。
1. 构造器
在 java 中定义一个简单的用户类,以及构造函数
public class User { private String name; private String password; public User(String name, String password) { this.name = name; this.password = password; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
然而在 Scala 中,只需一代码即可跟上面的 Java 代码等价。
scala> class User(var name:String,var password:String) defined class User
然后创建一个 User 对象。
scala> val tony = new User("tony","123456") tony: User = User@6a0659ac
也可以用 case 类来推断出构造方法的参数都是val类型的
scala> case class ImmutableUser(name:String,password:String) defined class ImmutableUser scala> val user = ImmutableUser("tony","123456") user: ImmutableUser = ImmutableUser(tony,123456)
稍后,就会讲到case class。
2. 单例对象、伴生对象、Case Class、Trait
2.1 单例对象
在Scala学习笔记(二)中,讲述过Scala 中没有静态修饰符 static,在 object 下的成员全部都是静态的,而且 object 不能提供构造器参数。
那么,今天再补充一下,以 object 关键字定义的对象是一个单例对象。
先上一段代码。
scala> object Singleton { | def test() = println("test singleton") | } defined object Singleton scala> Singleton.test() test singleton
经过查看 class 文件获取它的源码,Singleton 生成了一个懒汉模式的单例类。
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // import scala.Predef.; public final class Singleton$ { public static final Singleton$ MODULE$; static { new Singleton$(); } public void test() { .MODULE$.println("test singleton"); } private Singleton$() { MODULE$ = this; } }
2.2 伴生对象
如果在类中声明了与该类相同的名字的 object 则该object 是该类的“伴生对象”。
相对于伴生对象,单独的 object 对象是独立对象(Standalone Object)。他们的主要用途是可以用于工具类,或者定义 Scala 程序的入口等等。
来看一个伴生对象和伴生类使用的例子。
/** * Created by tony on 2017/2/20. */ class User(var name:String,var age:Int) { def greet: Unit = { println("hi, My name is "+name) } override def toString: String = { "name is "+ name + ", age is " + age } } object User { def addAge(u: User) = u.age +1 } object Main extends App { //伴生对象可以引用类的私有变量 val user = new User("Tony",20) println(user.age) // 20 user.age = User.addAge(user) //类可以引用伴生对象的私有变量 user.greet // hi, My name is Ton println(user) // name is Tony, age is 20 }
2.3 Case Class
case class 跟普通 class 的区别在于
- 初始化的时候不需要 new
- 自动创建伴生对象
- 默认是可以序列化的,实现了 Serializable
- 构造函数的参数都是 val 类型的
- 支持模式匹配。
- 实现自己的 toString、hashCode、copy、equals 方法
scala> case class User(name:String,age:Int) defined class User scala> val tony = User("Tony",20) tony: User = User(Tony,20) scala> tony.age = 21 <console>:14: error: reassignment to val tony.age = 21 ^
模式匹配,后面的文章会讲到。
2.4 Trait
Scala 不提供接口,而提供类似接口的 Trait ,跟接口不同的是 Trait 可以写方法的实现。这一点跟 Java 8 接口的默认方法很相似。
scala> trait Fly { | def fly() | } defined trait Fly scala> trait Swim { | def swim() | } defined trait Swim scala> class Duck extends Swim { | def swim() { | println ("duck can swim") | } | } defined class Duck scala> class Swan extends Swim with Fly { | def swim() { | println ("swam can swim") | } | | def fly() { | println ("swam can fly") | } | } defined class Swan scala> val swam = new Swan() swam: Swan = Swan@1d0d6318 scala> swam.swim() swam can swim scala> swam.fly() swam can fly scala>
定义两个Trait,“飞”和“游泳”。再定义两个类,“鸭子”和“天鹅”。鸭子会游泳,而天鹅既会游泳,也会飞。
对于 Trait 不止一个的类的时候,可以用 with
关键字来添加额外的 Trait。
例如:
extends Trait1 with Trait2 with Trait3
3. 继承
像 Java 一样,Scala 只支持单一继承,而不是多重继承。
总结
本篇内容只是 Scala 类相关内容的开头,后续会陆续整理。