scala的可见性,隐式值以及异常处理

可见性(了解)

public

scala中没有public关键字,scala类和属性都是默认公开的。

private

修饰属性和方法

class Student02 {
    private var id:Int=_
    var name:String=_
    def this(id:Int,name:String){
        this()
        this.id=id
        this.name=name
    }
    private def sayHello(): String ={
        s"hello $name"
    }
    override def toString: String = {
        s"$id\t$name"
    }
}
object Student02{
    def main(args: Array[String]): Unit = {
        val stu = new Student02(3,"zhaoliu")
        stu.id=4
        println(stu.sayHello())
        println(stu)
    }
}

修饰属性和方法时,只有类的内部和伴生对象可以使用,其他类均不可以访问

修饰扩展构造

class Student03 {
    var id:Int=_
    var name:String=_
    private def this(id:Int,name:String){
        this()
        this.id=id
        this.name=name
    }
}

仅伴生对象可见

修饰默认构造

private class Student03 {
    var id:Int=_
    var name:String=_
    private def this(id:Int,name:String){
        this()
        this.id=id
        this.name=name
    }
}

仅仅能在类的内部使用,伴生对象使用时,返回值必须为空(伴生对象可以直接类名.调用方法)

protected

修饰属性和方法

class Student04 {
    protected var id:Int=_
    var name:String=_
    def this(id:Int,name:String){
        this()
        this.id=id
        this.name=name
    }
    protected def sayHello(): String ={
        s"hello $name"
    }
    override def toString: String = {
        s"$id\t$name"
    }
}

本类和伴生对象以及子类可见

修饰扩展构造

class Student05 {
    protected var id:Int=_
    var name:String=_
    protected def this(id:Int,name:String){
        this()
        this.id=id
        this.name=name
    }
}

表示该扩展构造方法只能对本类和伴生对象以及子类可见

修饰默认构造

protected class Student05 {
    protected var id:Int=_
    var name:String=_
    protected def this(id:Int,name:String){
        this()
        this.id=id
        this.name=name
    }
}

其他类可以使用 Student05.apply() 调用,但构造方法只对本类,伴生对象以及子类可见

this限定

可以和private或者protected联合使⽤,可以将可⻅性缩⼩为本类的内部,去除伴⽣对象。

class Student04 {
    protected[this] var id:Int=1
}
object Student04{
    def main(args: Array[String]): Unit = {
        var st=new Student04
        st.id =10//error
    }
}
class SmallStudent04 extends Student04 {
    def sayHello()={
        println(s"${id}")
    }
}

包限定

class Student05 {
    private[demo12] var id:Int=10
}
class SmallStudent05 extends Student05 {
    def sayHello():Unit={
        println(s"${id}")
    }
}

当使用包限定时,private和protected就失效了,全部以包限定为准

将类的使用范围限定在某一个包下

final限定(掌握)

修饰类:最终类,不可以被继承
修饰⽅法:不能被覆盖
修饰属性:只能修饰 val 属性,不可以修饰局部变量(scala已经提供了val表示常量),当final修饰成
员变量,属性不可以被遮盖。( scala中只⽤val的成员变量才可以被覆盖 )

sealed(掌握)密封|闭包

Trait和class可以标记为 sealed ,这意味着必须在同⼀源⽂件中声明所有⼦类型这样就确保了所有的
⼦类型都是已知的。通常应⽤在case-class声明。

sealed class User
case class SmallUser(name:String) extends User
case class BigUser(name:String,age:Int) extends User
var a=Array[Any](new SmallUser("⼩学⽣"),new BigUser("⼤学⽣",18))
val u = a(1)
u match {
    case SmallUser(name) => println(name)
    case BigUser(name,age) => println(name+" | "+age)
    case _ => println("未知⽣物")
}

sealed修饰的 trait 的实现类必须和 trait 在同一个scala 源文件中

lazy加载(掌握)

Scala中使⽤关键字lazy来定义惰性变量,实现延迟加载(懒加载)。 惰性变量只能是不可变变量,并且只
有在调⽤惰性变量时,才会去实例化这个变量。

def getName():String={
    println("----getName-----")
    "zhangsan"
}
lazy val name:String=getName()
println(name)

函数对象(lambad表达式)

函数式接⼝

事实上在Java 8中也引⼈了函数式接⼝,类似Scala中的函数式对象。例如在Java中定义⼀个函数式接⼝:

@FunctionalInterface
public interface GreetingService {
    String sayHello(String name);
}

要求接⼝中只能有⼀个⽅法声明。只有函数式接⼝才可以使⽤lambda表达式做匿名类实现。

GreetingService gs=(String name) -> "hello "+ name;
String results = gs.sayHello("zhangsan");
System.out.println(results);

Scala这⻔语⾔在lambda编程的灵活性上是java⽆法媲美的。因为Scala在声明函数式对象(等价java函数
式接⼝)是⾮常轻松的。

1581492874757

例如以上案例的GreetingService如果使⽤Scala声明可以简写为如下:

val sayHello:(String)=>String = (name) => "hello ~"+name
println(sayHello("zhangsan"))

部分应⽤函数

在Scala中同样对所有的函数都可以理解为是⼀个 函数对象 。例如在Scala中可以将任意⼀个函数转变成
对象。例如如下定义⼀个sum函数。

def sum(x:Int,y:Int):Int={
    x+y
}

在Scala中可以尝试将⼀个函数转变成⼀个对象类型,如下:

scala> def sum(x:Int,y:Int):Int={
    | x+y
    | }
sum: (x: Int, y: Int)Int
scala> var sumFun = sum _
sumFun: (Int, Int) => Int = <function2>
scala> sumFun(1,2)
res0: Int = 3

通常将sumFun称为sum函数的部分应⽤函数,不难看出sumFun事实上是⼀个变量。该变量的类型是 (Int, Int) => Int 通常将该类型称为函数式对象。事实上以上的 (Int, Int) => Int是 Function2 的变体形式。因为Scala最多⽀持 Funtion0~22 种形式变体。例如:

class SumFunction extends ((Int,Int)=>Int){
    override def apply(v1: Int, v2: Int): Int = {
        v1+v2
    }
}
等价写法:
class SumFunction extends Function2[Int,Int,Int]{
    override def apply(v1: Int, v2: Int): Int = {
        v1+v2
    }
}
scala> sumFun.isInstanceOf[(Int,Int)=>Int]
res2: Boolean = true
scala> sumFun.isInstanceOf[Function2[Int,Int,Int]]
res3: Boolean = true

isInstanceOf该⽅法等价于java中的instanceof关键字。⽤于判断类型。

PartitalFunction 偏函数

偏函数主要适⽤于处理指定类型的参数数据,通常⽤于集合处理中。定义⼀个函数,⽽让它只接受和处
理其参数定义域范围内的⼦集,对于这个参数范围外的参数则抛出异常,这样的函数就是偏函数(顾名
思异就是这个函数只处理传⼊来的部分参数)。偏函数是个特质其的类型为PartialFunction[A,B],其中接
收⼀个类型为A的参数,返回⼀个类型为B的结果。

val pf1=new PartialFunction[Any,Int] {
    override def isDefinedAt(x: Any): Boolean = {
        x.isInstanceOf[Int]
    }
    override def apply(v1: Any): Int = {
        v1.asInstanceOf[Int]*2
    }
}
//偏函数的变体写法
val pf2:PartialFunction[Any,Int] = {case x:Int => x*2}
val a = Array(1,"a",2,"b",true,3)
//for(i<-a;if(i.isInstanceOf[Int])) yield i
val ints1 = a.collect(pf1)
println(ints1.mkString(" | "))
//偏函数的变体写法
val ints2 = a.collect(pf2)
print(ints2.mkString(" | "))

隐式值注入和转换(重点)

隐式值

object CustomImplicit {
    //声明隐式值
    implicit val s:String = "hello"
}
object TestImplicit {
    def main(args: Array[String]): Unit = {
        //引入隐式值     也可以直接写    implicit val s:String = "hello"
        import CustomImplicit._
        //获取上下文中的一个String类型的隐式值,要求类型唯一
        var b:String = implicitly[String]
        print(s"b的值为:$s")
    }
}

implicit 声明隐式值,implicitly 使用隐式值

隐式注入

object CustomImplicit {
    //声明隐式值
    implicit val s:Int = 1
    //隐式注入
    implicit val name:String = "云龙兄"
}
object TestImplicit {
    def main(args: Array[String]): Unit = {
        //引入隐式值
        import CustomImplicit._
        sayHello("你好啊!")
        sayHello("吃了吗?")("云飞兄")
    }
    def sayHello(message:String)(implicit name:String): Unit ={
        println(s"$message\t$name")
    }
}

要求上下⽂环境中,必须有⼀个String类型隐式值,系统会⾃动注⼊

注意implicit 放在参数上时,放在最后一个参数上

隐式转换(把不兼容转换为兼容)(参数类型)

object CustomImplicit {
    //声明隐式转换
    implicit def stringToDate(s:String):Date = {
        val sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
        sdf.parse(s)
    }
}
object TestImplicit {
    def main(args: Array[String]): Unit = {
        //引入隐式值
        import CustomImplicit._
        showTime("2008-8-8 19:49:57")
    }
    def showTime(date:java.util.Date): Unit ={
        println("此时的时间为:"+date.toLocaleString)
    }
}

隐式增强(类)

class Pig(var name:String) {
    def eat(): Unit ={
        println("吃")
    }
    def sleep(): Unit ={
        println("睡")
    }
}
trait Flyable {
    def fly(): Unit
}

原始的解决方式—动态trait植入

object TestImplicit {
    def main(args: Array[String]): Unit = {
        val pig1 = new Pig("佩奇") with Flyable {
            override def fly(): Unit = {
                println(s"$name\t会飞")
            }
        }
        pig1.eat()
        pig1.sleep()
        pig1.fly()
    }
}

隐式增强的方式

//声明隐式增强
implicit class PigImplicit(pig:Pig){
    def fly()={
        println(s"${pig.name}\t会飞")
    }
    def speek(name:String)={
        println(s"${pig.name}\t哼哼叫")
    }
}
def main(args: Array[String]): Unit = {
    //引入隐式值
    import CustomImplicit._

    val pig2 = new Pig("乔治")
    pig2.eat()
    pig2.sleep()
    pig2.fly()
    pig2.speek()
}

异常处理

Java:区分已检查(必须处理)和未检查(可选)异常、捕获有顺序限制,由⼩->⼤

public class JavaExceptions {
    public static void main(String[] args) {
        try {
            throw new IOException("我⾃⼰抛出的~");
        } catch (IOException e) { //由精准--> 模糊
            e.printStackTrace();
        }catch (ArithmeticException e){
            e.printStackTrace();
        }
        catch (Throwable e){
            e.printStackTrace();
        } finally {
            System.out.println("最终执⾏");
        }
    }
}

Scala:不区分已检查和未检查异常,捕获按照写case 进⾏匹配

object ScalaExceptions {
    def main(args: Array[String]): Unit = {
        try {
            throw new IOException("我⾃⼰抛出的~")
        }catch {
            case e:ArithmeticException =>{
                println("ArithmeticException")
                e.printStackTrace()
            }
            case e: Throwable =>{
                println("Throwable")
                e.printStackTrace()
            }
            case e: IOException =>{
                println("IOException")
                e.printStackTrace()
            }
        } finally {
            System.out.println("最终执⾏")
        }
    }
}

scala中异常可以不处理,处理异常时没有java中必须由小到大catch的要求,从上到下逐个进行匹配,有一个catch到,直接打印处理结果。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值