单例类
由于Scala没有静态方法和静态类,通过object去定义静态方法或静态对象。(对象是单例的)
object User {
def sayHello:(String)=>String = (name)=> "Hello ~"+name
def sayHello1(name:String):String={
"Hello ~"+name
}
}
类
必须要求在构造方法的第一行显式调用this(),其中_表示参数赋值为默认值,因为Scala中class默认构造器是在类上声明的
class User {
var id:Int = _
var name:String= _
var birth:Date = _
def this(id:Int,name:String,birth:Date){
this()
this.id=id
this.name=name
this.birth=birth
}
override def toString: String = {
s"$id\t$name\t$birth"
}
}
def this(参数) 构造器重载
使用该种方式声明构造类似于Java编程,但是要求在构造的第一行必须显示调用默认构造方法。
class User(var age:Int,var name:String) { //默认构造器
var birth:Date = _
def this(age:Int,name:String,birth:Date){
this(age,name)
this.birth=birth
}
override def toString: String = {
s"$age\t$name\t$birth"
}
}
var u1=new User() //error
var u2=new User(1,"zs")
var u3=new User(1,"zs",new Date())
伴生对象创建类
- apply
使用伴生对象可以方便的创建对象,只需要覆盖对应的apply方法,如下:
class User(var age:Int,var name:String) {
var birth:Date = _
def this(age:Int,name:String,birth:Date){
this(age,name)
this.birth=birth
}
override def toString: String = {
s"$age\t$name\t$birth"
}
}
object User{
def apply(age: Int, name: String): User = new User(age, name)
def apply(age: Int, name: String,birth:Date): User = new User(age, name,birth)
}
创建对象无需new
var u3=User(1,"zs",new Date())
var u4=User(1,"zs",new Date())
- unapply
用于将一个实体对象的属性解码出来
class User(var age:Int,var name:String) {
var birth:Date = _
def this(age:Int,name:String,birth:Date){
this(age,name)
this.birth=birth
}
override def toString: String = {
s"$age\t$name\t$birth"
}
}
object User{
def apply(age: Int, name: String): User = new User(age, name)
def apply(age: Int, name: String,birth:Date): User = new User(age, name,birth)
def unapply(u: User): Option[(Int, String,Date)] ={
Some(u.age,u.name,u.birth)
}
}
val u = new User(1,"zs",new Date())
u.name="zhangsan"
var User(age,name,birth)=u
println(s"$age\t$name\t$birth")
抽象类
abstract class Animal(name:String){
def eat():Unit{
println("this is animal")
}
def sleep():String
}
Trait/特质(接口)
trait Speakable{
def speek():Unit
}
trait Flyable{
def fly():Unit
}
集成和实现
与Java中的大致相同
class Bird(name:String) extends Animal(name:String) with Flyable with Speakable {
override def sleep(): String = {
s"$name 睡觉"
}
override def fly(): Unit = {
println(s"$name 会飞!")
}
override def speek(): Unit = {
println(s"$name 唧唧咋咋!")
}
}
class Dog(name:String) extends Animal(name:String) with Speakable {
override def sleep(): String = {
s"$name 睡觉!"
}
override def speek(): Unit = {
println(s"$name 旺旺叫!")
}
}
var d:Animal=new Dog("小黑")
var b:Animal=new Bird("小麻雀")
var d2:Dog=d.asInstanceOf[Dog]
d2.speek()
动态植入
在覆盖有实现的方法必须添加overwrite
一个类只能继承一个类(抽象)with多个trait
class A extends B with C with D{} // B既可以是Trait也可以是Class,但是C/D必须是Trait
class SmallBird(var name:String) extends Animal (name:String) with Speakable {
override def sleep(): String = {
s"$name 会睡觉!"
}
override def speek(): Unit = {
println(s"$name 咿咿呀呀!")
}
override def eat(): Unit = {
println(s"$name 吃鱼!")
}
}
var sb=new SmallBird("丑小鸭") with Flyable{
override def fly(): Unit = {
println(s"$name 会飞!")
}
}
sb.fly()
self
- 等价于this关键字,在this出现混淆时使用self给this关键字起别名
class User(var name:String) {
self =>
def setName(name:String):Unit={
self.name=name
}
def getName():String={
self.name
}
}
- Trait强制混合
如下:一个类实现Flyable接口,必须要集成或实现Bird
trait Flyable {
this:Bird =>
}
abstract class Bird {}
class FlyFish extends Bird with Flyable {
}
Case class
case class 就像常规类,case class适用于对不可变数据进行建模
case class User(name:String,age:Int)
var u1= User("zs",19)
var u2= User("zs",19)
println(u1==u2) //true
var u1= new User("zs",19)
var u2= new User("zs",19)
println(u1==u2) //true
与普通的class不同的是,CaseClass创建的对象 == 比较的是对象的内容。通常用于只读数据的建模。可以简单的使用copy来实现两个对象间的值得传递
var u1= User("zs",19)
var u2= u1.copy(u1.name,20)
println(u2)
final
- 修饰类,表示最终类,该类无法被继承
- final修饰方法,表示方法不允许被覆盖
- final修饰属性,表示该属性不允许被子类覆盖,因为Scala使用val关键字表示属性能否被修改。
可见性
Scala中的默认可见性为public,但这是逻辑上的,实际上Scala中并没有public这个关键子,如果用public来声明一个类或成员,编译会报错。
class User {
var id=1
var name="zhanngsan"
var age=18
var birthDay = new Date ()
}
Private
- private修饰类
private修饰的类只能被同包下的子类继承,并且同包继承的类也必须是private修饰。这样才不会改变原始父类的可见性。
package com.baizhi.demo08
import java.util.Date
private class User {
var id=1
var name="zhanngsan"
var age=18
var birthDay = new Date ()
}
子类
package com.baizhi.demo08
private class SmallUser extends User {
}
- private修饰属性|方法
private修饰属性表示该属性/方法只对本类|伴生对象可见,其他均不可见
package com.baizhi.demo08
import java.util.Date
private class User {
private var id=1
var name="zhanngsan"
var age=18
var birthDay = new Date ()
private def eat():Unit={
println("吃!")
}
}
object User{
def main(args: Array[String]): Unit = {
val user = new User()
user.eat()
user.id=2
}
}
Protected
- 修饰类对本包可见。
- 修饰属性和方法只能在本来或本类的子类和伴生对象中访问
this限定
可以去除对伴生对象的可见性
表示去除伴生对象可见性,严格限定该属性只能在本类中或者子类中使用。
class Student(name:String) {
var id=1
protected|private[this] var sex=true
def sayHello():Unit={
println(this.name)
}
}
object Student{
def apply(name: String): Student = new Student(name)
}
package限定
表示当前的类、属性、方法可以在指定的包下可见
sealed(密封)
Trait和class、case class可以标记为sealed,这意味着必须在同一文件中声明所有子类,这样就确保了所有子类都是已知的
sealed case class Message(msg:String,code:Int)
class InfoMessage(msg:String,code:Int) extends Message(msg:String,code:Int)
class ErrorMessage(msg:String,code:Int) extends Message(msg:String,code:Int)
class WarnMessage(msg:String,code:Int) extends Message(msg:String,code:Int)