Scala进阶

Scala进阶

定义类

class User{

  //类成员必须初使化,
  var name:String=null

  @BeanProperty var alias:String="caspar"

  private[this] var age=null

  //println将作为主构建器中的一部分,在创建对象时被执行
  println("constructing user ........")

  //重写toString()方法
  override def toString()= name + ":"+ alias

}

//通过继承App,定义一个应用程序对象
//扩展App后,程序可以直接运行,而不需要自己定义main方法,代码更简洁
object UserTest extends App{
  var user = new User()
  user.name="caspar" //直接修改,但其实调用的是p.name_=("jonh")
  user.alias_=("csp") 
  println(user)
}

*Scala会默认生成name(),name_=(.)和构造函数() 
*name()对应java中的getName()方法 
*name_=()对应java中的setName()方法 
*定义的是公有成员,但生成的字节码中是以私有方式实现的,生成的getter,setter方法是公有的 
*定义私有成员,其getter,setter也是私有的 
*如果将成员域定义为private[this],则不会生成getter,setter方法 
*private[this]只能由该类创建的对象本身能访问到,因此它定义的类成员也称为对象私有成员 
*如需要像java中一样自动产生getter,setter方法,需要引用scala.reflect.BeanProperty,采用注解的方式修饰变量 
*当主构造器的参数不用var或val修饰的时候,参数会生成类的私有val成员,并且不会产生getter和setter方法 


自定义getter和setter方法 

def name=name  
def name_=(name:String){  
    this.name=name
}


定义类的同时定义主构造器 

class User(val name:String,val age:Int){
  override def toString: String = name +":"+ age
}

object Test extends App{
  val user = new User("caspar",27)
  println(user)
}


主构建器带默认参数

class User(val name:String="",val age:Int=28){...} 


主构造器中参数带访问控制符 

class User(val name:String,private val age:Int=19){
  override def toString: String = name +":"+ age
  println("age"+age)
}

object Test extends App{
  val user = new User("caspar",12)
  //user.age //error inaccessible
  println(user)
}


类名后面紧跟private关键字可以将主构建器设为私有,不允许外部使用

class User private(var name:String,var age:Int){...} 


*如果禁用掉了主构建器,则必须使用辅助构造函数来创建对象 
*辅助构建器的名称为this,java中的辅助构造函数与类名相同,这常常会导致修改类名时出现不少问题,scala语言避免了这样的问题 
*调用辅助构造函数时,必须先调用主构造函数或其它已经定义好的构造函数 

只有辅助构造函数的类

class User(){
  //类成员
  private var name:String=null
  private var age:Int=18
  private var sex:Int=0

  //辅助构造器
  def this(name:String){
    this()
    this.name=name
  }
  def this(name:String,age:Int){
    this(name)
    this.age=age
  }
  def this(name:String,age:Int,sex:Int){
    this(name,age)
    this.sex=sex
  }
  override def toString: String = name+":"+age+":"+sex
}

object Test extends App{
  val user1 = new User("caspar",12,1)
  val user2 = new User("caspar",12)
  val user3 = new User("caspar")
  println(user1)
  println(user2)
  println(user3)
}

带有主构建函数和辅助构建函数的类

class User(var name:String,var age:Int){
  //类成员
  private var sex:Int=0

  def this(name:String,age:Int,sex:Int){
    this(name,age)
    this.sex=sex
  }
  override def toString: String = name +":"+age+":"+sex
}

object Test extends App{
  val user1 = new User("caspar",12,1)
  val user2 = new User("caspar",12)
  println(user1)
  println(user2)
}


Abstract类

抽象类是一种不能被实例化的类,抽象类中包括了未实现的抽象方法,这些方法由子类去扩展自己的实现 
子类继承抽象类,抽象类中的方法必须有实现,否则子类也必须定义为抽象类 
抽象类也可以直接new一个匿名类对象,在该匿名类对象中对方法加以实现 

scala中的抽象类定义 

abstract class User {
  def login:Unit
}

除抽象方法外,抽象类中还可以有抽象字段: 

abstract class User {
  def login:Unit
  //抽象字段,一般类中定义字段必须初始化,而抽象类中则没有这要求
  var age:Int
  var name:String
}

//通过主构造器对name参数进行了初始化
class Waiter(var name:String) extends User{
  override def login: Unit = {
    println("waiter "+name+" is logined")
  }
  override var age: Int = _
}

class Customer extends User{
  //对父类中的方法进行实现,注意这里面可以不加override关键字
  def login: Unit = {
    println("Customer "+name+" is logined")
  }

  override var age: Int = 0
  override var name: String = null

}
object Test extends App{
  val user = new Customer()
  user.name = "caspar"
  user.login

  val waiter = new Waiter("caspar")
  waiter.login
  
  //下面的代码定义了一个匿名类,并且进行了实例化
  //直接new User,后面跟的是类的内容
  //User是一个抽象类,它是不能被实例化的
  //这里能够直接new操作是因为我们扩展了User类,这个类是匿名的,只能使用一次
  var somebody = new User {
    override def login: Unit = {
      println("User "+name+" is logined")
    }
    override var name: String = _
    override var age: Int = _
  }
  somebody.name="caspar"
  somebody.login 
}

伴生对象与伴生类

class User {
  def print:Unit ={
    UserTest.num+=1
    println(
      UserTest.num+".\tname:"+name+"\tage:"+age )
  }
  var age:Int = _
  var name:String = _
}

object UserTest extends App{
  var num = 0
  var user = new User()
  user.name="caspar"
  user.age=29
  user.print
  user.print
  user.print
}

object UserTest被称为class User的伴生对象,而class User被称为object Usertest的伴生类 

内部类

*内部类可以像类的其它成员一样访问外部类的私有成员 *外部类不能访问内部类的成员域,但内部类可以直接访问外部类成员域,即使private私有的

class User {
  def print:Unit ={
    println(
      "name:"+name+"\tage:"+age )
  }
  var name:String = _
  private var pwd:String = "password"
  var age:Int=18

  private[this] def info: String = "name:"+name+"\tage:"+age

  class SocialAccount(var google:String){
    var qq:String = _
    var email:String = _
    var facebook:String= _

    //内部的类可以直接访问外部类的成员变量和成员方法,即使是private
    override def toString: String = info+"\tpwd:"+pwd+"\tqq:"+qq+"\temail:"+email+"\tfacebook:"+facebook+"\tgoogle"+google
    def print:Unit ={
      println(this)
    }

  }
}

object Test extends App{
  val user = new User
  user.name= "caspar"
  user.age=19
  user.print
  var a = new user.SocialAccount("google account")
  a.facebook="facebook account"
  a.qq="qq account"
  a.email="test@test.com"
  a.print
}

类的继承extends及多态

*“多态”(Polymorphic)也叫“动态绑定”(Dynamic Binding)、“迟绑定”(Late Binding),指“在执行期间(而非编译期间)判断所引用对象的实际类型,根据其实际类型调用其相应的方法。”即指子类的引用可以赋给父类,程序在运行时根据实际类型调用对应的方法 
*override方法重写指的是当子类继承父类的时候,子类重写父类的方法,方法重写是实现多态和动态绑定的关键 
*scala中的方法重写同java一样,也是利用override关键字标识重写父类的算法 

类的继承

class User {
  def print:Unit ={
    println(
      "name:"+name+"\tage:"+age )
  }
  var name:String = _
  private var pwd:String = "password"
  protected var phone:String = "12345678900"
  var age:Int=18
}

class Customer(var vip:Boolean) extends User{
  //子类可以访问父类的protected属性和方法,但不能访问private属性和方法

  //重写了自己的实现
  override def print: Unit = println("Customer name:"+name+"\tCustomer age:"+age+"\tvip:"+vip+"\tphone:"+phone)
}

object Test extends App{
  //User类的引用可以指向User类的任何子类
  val c:User = new Customer(false)
  c.name= "caspar"
  c.age=19
  //c.phone =10  这里不能访问到protected phone
  c.print //程序会根据实际类型调用对应的不同子类中的print()方法
}

构造函数执行顺序

class User {
  println("第一行输出:User.....")


  def print:Unit ={
    println(
      "name:"+name+"\tage:"+age )
  }
  var name:String = _
  private var pwd:String = "password"
  protected var phone:String = "12345678900"
  var age:Int=18
}

class Customer(var vip:Boolean) extends User{
  var qq:String = _
  var email:String = _

  def this(vip:Boolean,qq:String,email:String){
    this(vip)
    this.qq = qq
    this.email = email
    println("第二行输出:Customer this(...)...")
  }

  println("第三行输出:Customer....")

  //子类可以访问父类的protected属性和方法,但不能访问private属性和方法
  override def print: Unit = println("第四行输出:Customer name:"+name+"\tCustomer age:"+age+"\tvip:"+vip+"\tphone:"+phone)
}

object Test extends App{
  val c:User = new Customer(false,"q1234677","email@test.com")
  c.name= "caspar"
  c.age=19
  //c.phone =10  这里不能访问到protected phone
  c.print
}

Trait

Scala和Java语言一样,采用了很强的限制策略,避免了多种继承的问题。在java语言中,只允许继承一个超类,该类可以实现多个接口,但java接口有其自身的局限性:接口中只能包括抽象方法,不能包含字段、具体方法。 
Scala语言利用Trait解决了该问题,在scala的trait中,它不但可以包括抽象方法还可以包含字段和具体方法。 
使用with实现Trait接口 
Trait中可以带有具体字段和具体方法的实现 
trait有自己的构造器,它是无参构造器,不能定义trait带参数的构造器 

trait的构造顺序 
1. 如果有超类,则先调用超类的构造器 
2. 如果有父trait,它会按照继承层次先调用父trait的构造器 
2. 如果有多个父trait,则按顺序从左到右执行 
3. 所有父类构造器和父trait被构造完之后,才会构造本类 

trait User {
  //定义一个抽象方法,注意不需要加abstract
  def login(id:String):String
  def add(o:Any):Boolean
  def update(o:Any):Int
  def query(id:String):List[Any]
}

trait Vip {
  def info(vip:Boolean):Boolean
  //带有具体字段
  private var num = 0
  
  //带有具体方法和属性的实现
  def upgrade={
    num+=1
    println("升级成"+num+"号vip 会员")
  }
}

class Customer extends User with Vip{
  override def login(id: String)=id

  override def add(o: Any): Boolean = {
    if(o==null) false
    else true
  }

  override def update(o: Any): Int = {
    if(o==null) 0
    else 1
  }

  override def query(id: String): List[Any] = List(id,"aaa","bbb")

  override def info(vip: Boolean): Boolean = vip
}

object Test extends App{
  val u = new Customer
  Predef println u.login("userid 001")
  println(u.add("add user"))
  println(u.update("update user"))
  println((u query "userid 001").mkString(","))
  println("vip:"+u.info(false))
  u.upgrade
  u.upgrade
}

自身类型(=>)

用法一

class OuterClass { 
    outer => //定义了一个外部类别名
    val v1 = "here"
    class InnerClass {
        // 用outer表示外部类,相当于OuterClass.this
        println(outer.v1) 
    }
}

用法一

trait User {
  //定义一个抽象方法,注意不需要加abstract
  def login(id:String):String
}

class Customer{
  //self:User => 要求Customer在实例化时或定义Customer的子类时
  //必须混入指定的User trait,这个User类型也可以指定为当前类型
  self:User=>
}

//类Test扩展Customer的时候必须混入trait User
//否则的话会报错
object Test extends Customer with User{
  override def login(id: String): String = id+" login..."

  def main(args: Array[String]): Unit = {
    println(login("001"))
  }
}

包对象

包对象主要用于将常量、工具函数,使用时直接通过包名引用 
包对象的定义

package com.scala.test

利用package关键字定义单例对象

package object Id{
  var id=0
  def autoIncrementId:Int={
    id+=1
    id
  }
}

object Test extends App{
  println(Id.autoIncrementId)
  println(Id.autoIncrementId)
  println(Id.autoIncrementId)
}

访问控制

在java语言中,主要通过public、private、protected及默认控制来实现包中类成员的访问控制,当定义一个类时,如果类成员不加任何访问控制符时,表示该类成员在定义该类的包中可见。在scala中没有public关键字,仅有private 和 protected访问控制符,当一个类成员不加private和protected时,它的访问权限就是public。下面逐个进行讲解:

private 成员

private成员同java是一样的,所有带该关键字修饰的成员仅能在定义它的类或对象中使用,在外部是不可见的

protected 成员

在java语言中,protected成员不但可以被该类及其子类访问,也可以被同一个包中的其它类使用,但在scala中,protected成员只能被该类及其子类访问

无修饰符成员

无修饰符的成员同java 的public,可以在任何位置进行访问

范围保护

在scala中提供了更为灵活的访问控制方法,private、protected除了可以直接修饰成员外,还可以以private[X]、protected[X]的方式进行更为灵活的访问控制,这种访问控制的意思是可以将private、protected限定到X,X可以是包、类,还可以是单例对象

private[this],限定只有该类的对象才能访问,称这种成员为对象私有成员

private,定义的类及伴生对象可以访问

访问规则表

修饰符 访问范围
无任何修饰符 任何地方都可以使用
private[scala] 在定义的类中可以访问,在scala包及子包中可以访问
private[this] 只能在定义的类中访问,即使伴生对象也不能访问团
private 在定义的的类及伴生对象中可以访问,其它地方不能访问
protected[scala] 在定义的类及子类中可以访问,在scala包及子包中可以访问
protected[this] 只能在定义的类及子类中访问,即使伴生对象也不能访问
protected 在定义的类及子类中访问,伴生对象可以访问,其它地方不能访问

import

隐式引入

可以直接使用包中或对象中所有的类和方法,称这种引入会隐式引入 
scala默认导入以几个包: 
import java.lang_ 
import scala._ 
import Predef._ 

重命名

scala中允许对引入的类或方法进行重命名,如果我们需要在程序中同时使用java.util.HashMap及scala.collection.mutable.HashMap时,可以利用重命名的方法消除命名冲突的问题 
将java.util.HashMap重命名为JavaHashMap 
import java.util.{ HashMap ⇒ JavaHashMap } 
import scala.collection.mutable.HashMap 

类隐藏

通过HashMap⇒ _,这样类便被隐藏起来了 
import java.util.{HashMap⇒ _,_} 
import scala.collection.mutable.HashMap 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值