4. OOP
4.1. 类class
4.1.1. 定义
例子1:
class User {
var name = "anonymous"
var age:Int = _
val country = "china"
def email = name + "@mail"
}
使用:
val u = new User
// var定义的属性可读可写
u.name = "qh"; u.age = 30
println(u.name + ", " + u.age) // "qh, 30"
// val 定义的属性只读不可写
u.country = "usa" // 报错
println(u.country) // "china"
// def 定义的是方法, 每次调用时重新计算
u.email // "qh@mail"
例子2:
class Person(ln : String, fn : String, s : Person = null) {
def lastName = ln; // 用def定义后才是属性,ln,fn,s不可见
def firstName = fn;
def spouse = s;
def introduction() : String =
return ("Hi, " + firstName + " " + lastName) +
(if (spouse != null) " and spouse, " + spouse.firstName + " " + spouse.lastName + "."
else ".");
}
// 调用
new Person("aa","bb", new Person("cc","dd")).introduction();
4.1.2. 构造方法
class c1(x:String) // 等同于:class c1(private var x:String)
val o1 = new c1("aaa")
o1.x // 报错,因为是private的,定义成 class c1(var x:String) 才能这样用
例子1:
object construct1 {
class c1(name:String, age:Int) { // (1)直接在类定义处
def this() { this("anonymous", 20) } // (2)用this定义
def m1() = { printf("%s=%d\n", name, age) }
}
def main(args:Array[String]) = {
new c1().m1()
new c1("qh", 30).m1()
}
}
编译:fsc construct1.scala
运行:java construct1
例子2:继承中的构造方法:
class c2(name:String, age:Int, female:Boolean=false)
extends c1(name,age) {
override def toString = { name + "," + age + "," + female }
}
4.1.3. override
不同于Java的使用 @Override,或者直接使用相同名字覆盖父类方法。
override def toString = { name + "," + age + "," + female }
如果是覆盖抽象方法,可以不用overriade关键字。
4.1.4. object单例对象
如:
Java |
Scala |
public class User { private String name; private User(String name) { this.name=name; } public static User instance(String name) { return new User(name) } } |
object User { var name:String = _ def apply(name:String){this.name=name; this} override def toString = "name: " + name } 调用: val u = User("qh") // "name: qh"
|
4.1.5. 静态方法
Scala没有静态方法,类似静态方法的函数定义在object中:
object Stringx {
def left(s0:String, s:String) = ...
}
直接调用Stringx.left(s0, s),或者 Stringx left (s0, s)
定义在object中的implicit方法也能被直接调用:
例如:
--------- ImportSub.scala
object ImportSub {
def fac(n: Int) = 1 to n reduceLeft (_ * _)
implicitdef foo(n: Int) = new { def ! = fac(n) }
}
import ImportSub._
object ImportMain {
def main(args : Array[String]) : Unit = {
println(5!) // 调用ImportSub中定义的implicit函数
}
}
4.1.6. case class(条件类)
例如:
case class Person(name:String, age:Int)
特殊之处:
l 新建类实例不用new Person(..),直接用Person("qh",20)
l 自动定义好getXX方法,Person("qh",20).name // "qh"
l 提供默认的toString(), Person("qh",20) // "Person(qh,20)"
l 结合类继承可以通过模式匹配进行分解
例子1:
abstract class Person
case class Man(power:Int) extends Person
case class Woman(beauty:Int, from:String) extends Person
val w1 = Woman(100,"china")
val w2 = w1.copy(from="usa") // Woman(100,"usa")
def f(t:Person) = t match {
case Man(x) => "man's power:" + x
case Woman(x,y) => y + " beauty:" + x
}
f(Man(100)) // man's power:100
f(Woman(90, "china")) // china beauty:90
注:基本类型直接可以用math case
例子2:可变的类状态
case class C1(var s: String, var ops: Int) {
def >>= (f: (String=>String)) = {
s = f(s) // s改变
ops += 1 // ops改变
this // 返回自身,可以连续调用
}
}
val C1(res, ops) = C1("ab", 0) >>= (_ * 3) >>= (_ drop 3)
// res="ab"->"ababab"->"bab", ops=0-> 0+1+1->2
例子3:用case class代替tuple
val p = ("qh",20) // p._1 = "qh", p._2 = 20;好处是简洁,但无意义
case class person(name:String, age:Int)
val p = person("qh",20) // p.name = "qh", p.age = 20; 好处是有名字,自说明,可读性强
例子4:用case class来描述元数据
xml的版本:
<todo name = "housework">
<item priority = "high">Clean the hose</item>
<item priority = "medium">Wash the dishes</item>
<item priority = "medium">Buy more soap</item>
</todo>
(todo "housework"
(item (priority high) "Clean the house")
(item (priority medium) "Wash the dishes")
(item (priority medium) "Buy more soap"))
Scala的版本:
case class item(priority:String, s:String)
case class todo(name:String, items:List[item])
todo (name="housework",
items=item("high","Clean the house")::
item("medium","Wash the dishes")::
item("medium","Buy more soap")::Nil)
4.1.7. case object(条件单例对象)
比如定义一个标识类(而不是字符串):
case object Start
case object Stop
4.1.8. 枚举
Java中:
enum fruits { apple, banana, cherry }
在Scala中,则是:
sealed abstract class Fruits // sealed类似于java的final
case object Apple extends Fruits
case object Banana extends Fruits
case object Cherry extends Fruits
也可以是 case class
4.1.9. 属性和Bean
class c {
var name = "anonymous" // var定义的是r/w的属性
val age = 20 // val定义的是只r属性
}
val o = new c
o.name = "qh"
o.name // "qh"
o.age = 10 // 错误
o.age // 20
o.
例子2(定义get/set方法):
@reflect.BeanProperty var name = "anonymous"
}
val o2 = new c2
o2.name = "qh" // 也可以直接存取
o2.name // "qh"
o2.setName("james") // 增加了set/get方法
o2.getName() // "james"
4.1.10. 反射
Scala没有太特别的反射机制,使用java的即可,不过Scala在match..case中可以匹配类型:
case o:FooClass1 => ...
相关还有isInstanceOf[T], asInstanceOf[T]
例1(利用java的reflect):
"hello".getClass.getMethods.map(_.getName).toList.sortWith(_<_).mkString(", ")
例子2:
classOf[String] // 相当于java中的String.class
"aaa".isInstanceOf[String] // true
"aaa".asInstanceOf[String]
4.2. trait超级接口
注:trait [treit] n.特征,特点,特性
和Java的Interface类似,但可以定义实体方法,而非仅仅方法定义
trait可以看作有方法实现和字段的interface;代表一类事物的特性;
比如
Tom,可能是Engine 和Son两个trait的混合;
Sunny可能Sales、Son和Father三个trait的混合;
当在运行时往Son里面增加方法或者字段的时候,Tom和Sunny都得到增加的特性。
4.2.1. trait使用
trait Runnable {
def run(): Unit;
}
只是用一个接口,就用extends:
class c1 extends Runnable {...}
2个接口(或一个继承一个接口),用with而不是implements如下:
class c1 extends c0 with Runnable {
def run(): Unit = {...}
}
一个类可以组合多个trait:
class c1 extends t1 with t2 with t3 {...}
4.2.2. mixin
class Human
class Child
trait Dad {
privatevar children:List[Child] = Nil
def add(child:Child) = child :: children
}
class Man1(name:String) extends Human with Dad // 静态mixin
class Man2(name:String) extends Human // 先不具备Dad trait
val m1 = new Man1("qh")
m1.add(new Child)
val m2 = new Man2("小孩")
// m2.add(new Child) // 报错
val m2$ = new Man2("james") with Dad // 动态mixin
m2$.add(new Child)
4.3. 协变和逆变(co-|contra-)variance
4.3.1. 概念
使用“+”“-”差异标记
Function[A, B]和Function[-A, +B]的区别图示:
|
|
Function[A,B] |
Function[-A,+B] |
trait Queue[T] {} |
非变 |
trait Queue[+T] {} |
协变 如果S extends A (S为子类型,A为父类型), 则Queue[S]为子类型,Queue[A]为父类型 S <: A => Queue[S] <: Queue[A] |
trait Queue[-T] {} |
逆变 如果S extends A (S为子类型,A为父类型) 则Queue[S]为父类型,Queue[A]为子类型,和协变互逆 S <: A => Queue[S] >: Queue[A] |
-A是A的子集,叫逆变
+B是B的超集,叫协变
4.3.2. 类型上下界
|
|
<% |
foo[T <% Ordered[T]](...) 关系较弱:T能够隐式转换为Ordered[T] |
<: |
foo[T <: Ordered[T]](...) 关系较强:T必须是Ordered[T]的子类型,即T的类型范围小于Ordered[T],Ordered[T]为上界 |
>: |
foo[T >: A](...) 关系较强:T必须是A的父类型,即Tde类型范围大于A,A为下界 |
4.3.3. 协变、逆变结合上下界
例子1:
trait c1[+T] { def m[K >: T](x:K) = x } |
trait c1[-T] { def m[K <: T](x:K) = x } |
object c2 extends c1[Int] c2.m(3) // 3 c2.m(3.0) // 3.0 c2.m("abc") // "abc" |
object c2 extends c1[Int] c2.m(3) // 3 c2.m(3.0) // 报错 c2.m("abc") // 报错 |
|
|
例子2:
// 非变
case class T1[T](e:T)
val v1:T1[java.lang.Integer] = new T1(100)
val v2:T1[java.lang.Integer] = v1
v2.e // 100
val v3:T1[java.lang.Number] = v1 // 报错
// 协变
case class T1[+T](e:T)
val v1:T1[java.lang.Integer] = new T1(100)
val v2:T1[java.lang.Integer] = v1
v2.e // 100
val v3:T1[java.lang.Number] = v1 // 合法
v3.e // 100
val v4:T1[java.lang.Integer] = v3 //非法
// 逆变
class T1[-T](e:T)
val v1:T1[java.lang.Number] = new T1(100)
val v2:T1[java.lang.Number] = v1
val v3:T1[java.lang.Integer] = v1 // 合法
val v4:T1[java.lang.Number] = v3 // 非法
相关推荐
这个压缩包“scala学习资料(带书签)”提供了一个全面的学习路径,从基础到高级,帮助你深入理解和掌握Scala语言。 **入门篇** 1. **基础语法**:Scala的基础包括变量声明、类型系统、控制结构(如if/else、循环)...
### Scala学习笔记(全) #### 一、Scala概述与特点 Scala是一种多范式的编程语言,旨在集成面向对象编程和函数式编程的各种特性。它运行于Java平台(Java虚拟机JVM),并且能够完全兼容所有的Java程序。这使得Scala...
4. **Actor模型**:Scala集成了Akka库,提供了强大的并发和分布式计算支持。Actor模型允许并发执行而无需担心数据竞争,每个Actor都有自己的消息队列,通过异步消息传递进行通信。 5. **集合库**:Scala的集合库...
在"scala学习笔记整理"中,我们可以深入探讨以下关键知识点: 1. **基础语法**:Scala的基础语法与Java有相似之处,但也有很多独特的特点。例如,它支持变量的不可变性(immutability),使用`val`声明常量,`var`...
这个"scala学习-project.zip"压缩包很可能是为了帮助初学者或者开发者深入理解Scala语言而设计的一个实践项目。下面,我们将深入探讨Scala的一些核心概念和关键知识点。 1. **基础语法**:Scala的语法与Java有些...
### Scala学习之路(一)—— 开发环境搭建与首个程序 #### 一、Scala简介 Scala是一种多范式编程语言,旨在实现可扩展性,并融合了面向对象编程和函数式编程的最佳特性。作为一种与Java非常相似的语言,Scala能够...
同时,由于Scala构建在Java平台上,了解Java对于Scala学习者来说是非常有帮助的,因为可以将Java的生态和已有的知识无缝迁移到Scala上。 深入学习Scala,除了阅读书籍和文档之外,还需要大量的实践。参与开源项目、...
4. 集合库:Scala的集合库设计精良,包含各种高效的数据结构,如List、Set、Map等。这些集合不仅支持传统的OOP操作,还提供了丰富的函数式API,如map、filter、fold等,方便进行数据处理。 5. 特性与模式匹配:...
### Spark+Scala 学习知识点概述 #### 一、Scala语言基础 **1. Scala语言简介** Scala是一种融合了面向对象编程与函数式编程特性的现代编程语言。它旨在简化编程,提供更简洁、强大的代码编写方式。Scala运行在...
4. 并发编程:Scala提供了Actor模型,这是一种轻量级的并发机制,使得处理并发问题变得更加简单和高效。 5. Akka框架:Akka是用Scala编写的开源框架,用于构建高度可扩展、容错的应用程序,它充分利用了Scala的...
4. **函数式编程**:Scala鼓励使用不可变数据结构和高阶函数,函数是一等公民,可以赋值给变量,作为参数或返回值。λ表达式(匿名函数)和闭包也是重要的概念。 5. **类型推断**:Scala具有强大的类型推断能力,...
通过学习和使用Scala SDK,开发者可以利用其丰富的语言特性来构建复杂的软件系统,尤其是在大数据处理、Web应用、云计算等领域,Scala已经展现出了强大的生命力。例如Apache Spark,一个流行的分布式计算框架,就是...
标题“Akka Scala 学习高清原版pdf”表明该文档是一个专注于Scala语言在Akka框架中应用的指南,而“描述”则指出文档内容涵盖Scala实现的Akka并发编程。标签“Akka scala 并发 actor”则进一步具体化了文档内容,即...
在"scala学习资料,主题提取学习资料"这个压缩包中,我们可以预见到包含了一系列帮助学习Scala编程以及主题提取技术的资源。 Scala的基础知识点包括: 1. **基本语法**:Scala的语法与Java有诸多相似之处,但更加...
Scala 语言详细总结 Scala 是一门以 Java ...2. Scala 学习教程:Scala 学习教程提供了详细的学习资源,包括视频、文档和实践项目。 3. Scala 社区:Scala 社区是一个活跃的社区,提供了许多有用的资源和讨论论坛。
文件类型包括80个Scala源代码文件、4个XML配置文件、3个TXT文档、2个Markdown文档、2个Java源代码文件、1个GIT忽略文件、1个日志文件、1个JSON配置文件和1个Properties配置文件。该学习项目适合用于学习和实践Scala...
### Scala学习笔记关键知识点 #### 1. “均码”哲学与并发编程 - **“均码”哲学**: 指的是Scala设计时遵循的一种设计理念,即尽量保持语言的统一性和简洁性,使得不同的功能和特性能够以一种相似的方式进行处理。...
Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的特性,被广泛应用于大数据处理、分布式计算和高性能应用开发。...每个文档都配有实例和注释,便于理解和实践,是Scala学习者宝贵的资源。