Scala的class、object及修饰符

单例类

由于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) 

猜你喜欢

转载自blog.csdn.net/weixin_43655644/article/details/93653082