zoukankan      html  css  js  c++  java
  • Scala学习笔记-6-其他

    返回值类型可以不指定,建议指定

    Trait 特质

    • Traits 封装了方法和变量,和 Interface 相比,它的方法可以有实现,这一点有点和抽象类定义类似;
    • Scala 中类继承为单一继承,但是可以和多个 Trait 混合,这些 Trait 定义的成员变量和方法也就变成了该类的成员变量和方法;
    • 创建类的时候可以使用 extends 或 with 来混合一个 trait;
    • Traits 也算是继承制的父类,所以可以用 Traits 引用来接收子类对象(多态)
    • Trait 不能有任何“类”参数
    • Ordered Trait,一个用于对象之间进行比较的 Trait(类似 Java 的 Comparable 接口),只需要复写 compare 方法:=0,表示两个对象相同,>0表示前面大于后面对象,<0表示前面小于后面对象
    package test
    
    object MyTest extends Super {
      override def main(args: Array[String]): Unit = {
        val t: Test = new MyTest(1)
        t.hello()
        println(new MyTest(1) > new MyTest(100))
      }
    }
    
    trait Test {
      def hello(): Unit = println("hello scala")
    }
    
    class MyTest(i: Int) extends AnyRef with Test with Ordered[MyTest]{
      val value: Int = i
      override def compare(that: MyTest): Int = this.value - that.value
    }
    
    • Trait 用来实现可叠加的修改操作。
    package test
    
    object MyTest extends Super {
      override def main(args: Array[String]): Unit = {
        // 创建对象的时候再进行混合(这里也支持多个with混合)
        val t = new MyTest(1) with Test
        t.hello()
      }
    }
    
    // 定义一个抽象类
    abstract class Base {
      def hello(): Unit
    }
    
    // 这里继承了抽象类 Base,则该 trait 只能与实现了同样抽象类的子类混合
    trait Test extends Base {
      // 注意这里的修饰符 abstract override,这是必须的
      abstract override def hello(): Unit = {
        // 这里可以调用super(在普通类中这样是不行的),这里虽然父类中的方法是抽象的,但是这里其实是动态绑定
        super.hello()
        println("==OVER==")
      }
    }
    
    class MyTest(i: Int) extends Base {
      val value: Int = i
    
      override def hello(): Unit = {
        println(s"my value is ${this.i}")
      }
    }
    

    Package

    // 类似Java的写法
    package bobsrockets.navigation
    class Navigator
    
    // 类似C#的写法
    package bobsrockets.navigation {
      class Navigator 
    }
    
    • 支持嵌套
    package bobsrockets{
      package navigation{
        class Navigator{
          // 访问同一包中定义的类型,无需使用前缀,直接使用类型的名称即可访问
          var map =new StarMap   
        }
        class StarMap
      }
    
      class Ship {
        // 嵌套的 package 也可以在其父包中被同级别的其它类型直接访问,而无需使用全称(公共的包不用带,内部包名还是要带的)
        val nav= new navigation.Navigator
      }
    
      class fleets{
        class Fleet{
          // 内层的类型可以直接访问其外层定义的类型
          def addShip() {new Ship}
        }
      }
    }
    
    • 复杂嵌套下的访问
    package launch{
      class Booster3
    }
    package bobsrockets{
      package navigtion{
        package launch{
          class Booster1
      }
      class MissionControl{
        val booster1 =new launch.Booster1
        val booster2=new bobsrockets.launch.Booster2
        // Scala 提供了_root_,也就是所有最外层的类型都可以当成定义在_root_包中
        val booster3=new _root_.launch.Booster3
       }
      }
      package launch{
        class Booster2
      }
    }
    

    import

    • Scala 使用“_” 而非”*”作为通配符;
    • 可以出现在文件中任何地方
    • 可以 import 对象(singleton 或者普通对象)和 package 本身
    • 支持对引入的对象重命名或者隐藏某些类型
    // 导入具体某个类
    import bobsdelights.Fruit
    
    // 导入包下的所有类
    import bobsdelights._
    
    // 类似Java中的静态导入,可以直接使用 Fruits 中定义的对象
    import bobsdelights.Fruits._
    
    // 直接导入包,使用的时候用包名.类名的方式
    import java.util.regex
    
    // 仅导入Apple和Orange,隐藏其他类型
    import Fruits.{Apple, Orange}
    
    // 导入的同时重命名
    import Fruits.{Apple => MaIntosh, Orange}
    
    // 导入的包也可以重命名
    import java.{sql => S}
    
    // 隐藏掉Apple,导入其他所有
    import Fruits.{Apple => _, _}
    
    // 隐含的导入;后导入的会覆盖前导入的;Predef 为一对象(非报名),因此可以直接使用 Predef 对象定义的方法(静态引用);
    import java.lang._
    import scala._
    import Predef._
    

    访问控制

    • 私有成员
    class Outer{
      class Inner{
        private def f(){
          println("f")
        }
        class InnerMost{
          f() //OK
        }
      }
      // 这里Java中是可以的,但是Scala中不可以。Java 允许外部类型访问其包含的嵌套类型的私有成员,
      (new Inner).f();
    }
    
    • 保护成员
      在 Scala 中,由 Protected 定义的成员只能由定义该成员和其派生类型访问。
      在 Java 中,由 Protected 定义的成员可以由同一个包中的其它类型访问。
    class p{
      class Super{
        protected def f() {
          println("f")
        }
      }
      class Sub extends Super{
        f()
      }
      class Other{
        (new Super).f() //error: f is not accessible
      }
    }
    
    • 公开成员
      public 访问控制为 Scala 定义的缺省方式,不用写(根本就没这个关键字)

    为访问控制修饰符添加作用域

    private[x]或protected[x]
    其中 x 代表某个包,类或者对象,表示可以访问这个 Private 或的 protected 的范围直到 X。

    包对象

    • 定义在package.scala文件中,格式如下
    • 包中除了可以定义类、Trait、Object,还可以定义函数、变量
    • 每个包只有一个包对象,任何放在包对象的类型都可以认为是包自身的成员。
    package object test {
      def show(): Unit = println("i am test")
    }
    
    // 包对象也可以导入,然后调用
    import test.show
    

    Scala之偏函数Partial Function 与 case语句

    https://blog.csdn.net/bluishglc/article/details/50995939

    case与匿名函数

    // 完整写法
    List(1, 2 ,3 ,4 ,5).map((i: Int) => i * i)
    
    // 使用case语句构造匿名函数
    List(1, 2 ,3 ,4 ,5) map {
      case i => i * i
    }
    
    // case可以省略掉
    List(1, 2 ,3 ,4 ,5) map {
      i => i * i
    }
    

    case与偏函数

    val f1 = Future { Random.nextInt(10000) }
    
    // 偏函数
    val f2 = f1.andThen(new PartialFunction[Try[Int], Unit] {
      override def isDefinedAt(x: Try[Int]): Boolean = x.isSuccess
      override def apply(v1: Try[Int]): Unit = println(s"do something...  ${v1.get}")
    })
    
    f2 onComplete {
      case Success(value) => println(value)
      case Failure(exception) => println("ERR>>>", exception.getMessage)
    }
    
    // 使用case语句构造偏函数
    val f3 = f1.andThen({
      case v1 => println(s"do something...  ${v1.get}")
    })
    
    f3 onComplete {
      case Success(value) => println(value)
      case Failure(exception) => println("ERR>>>", exception.getMessage)
    }
    

    Scala之Future和Promise

    参考:Future和Promise

    基本使用

    implicit val ec: ExecutionContextExecutor = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(20))
    
    val f: Future[String] = Future[String] {
      Thread sleep 1000
      "hello scala"
    }
    
    // 完整写法,参数是一个函数:f: Try[T] => U
    f.onComplete((result: Try[String]) => result match {
      case Failure(exception) => println(exception)
      case Success(value) => println(value)
    })
    
    // 常用写法
    f onComplete {
      case Failure(exception) => println(exception)
      case Success(value) => println(value)
    }
    

    函数组合(Functional Composition)

    Future可以通过map、flatMap,filter和foreach等组合器,创建一个新的Future(可以有效避免Future中的多层嵌套)

    map

    val f1 = Future { List(1, 2, 3, 4, 5) }
    
    val f2 = f1.map(f1_v => {
      f1_v.appended(10).appended(11).appended(12)
    })
    
    f2 onComplete {
      case Success(value) => println(value)
      case Failure(exception) => println(exception)
    }
    

    flatMap

    FlatMap操作会把自身的值映射到其他future对象上,并随着该对象计算完成的返回值一起完成计算
    结合下面的For-comprehensions一起看

    val f1 = Future { List(1, 2, 3, 4, 5) }
    
    val f2 = f1.flatMap(f1_v => {
      Future {
        f1_v.appended(10).appended(11).appended(12)
      }
    })
    
    f2 onComplete {
      case Success(value) => println(value)
      case Failure(exception) => println(exception)
    }
    

    filter

    val f = Future { 5 }
    val g = f filter { _ % 2 == 1 }
    val h = f filter { _ % 2 == 0 }
    
    g onComplete {
      case Success(value) => println(value)
      case Failure(exception) => println(exception)
    }
    
    h onComplete {
      case Success(value) => println(value)
      case Failure(exception) => println(exception)
    }
    

    foreach 好像类似onSuccess???

    val f1 = Future { List(1, 2, 3, 4, 5) }
    
    f1.foreach(f1_v => {
      println(f1_v)
    })
    

    For-comprehensions 当异步f1的结果比异步f2的结果大的时候进行某些异步操作

    val f1 = Future { Random.nextInt(10000) }
    val f2 = Future { Random.nextInt(10) }
    
    // 第一种写法
    val f3 = for {
      f1_v <- f1
      f2_v <- f2
      if f1_v > f2_v
    } yield "成功"
    
    // 第二种写法
    val f3 = f1.flatMap(f1_v => {
      f2.withFilter(f2_v => f1_v > f2_v).map(_ => "成功")
    })
    
    f3 onComplete {
      case Success(value) => println(value)
      case Failure(exception) => println("ERR>>>", exception.getMessage)
    }
    

    recover

    val f1 = Future {
      Random.nextInt(10000)
    }
    
    // 使用recover,处理Future中的异常
    val f2 = f1.map((f1_v: Int) => {
      if (f1_v > 1000) {
        "success and do something..."
      } else {
        throw new Exception("user defined exception...")
      }
    }).recover(new PartialFunction[Throwable, String] {
      override def isDefinedAt(x: Throwable): Boolean = x.getMessage.contains("user defined")
    
      override def apply(v1: Throwable): String = v1.getMessage
    })
    
    // 如果没有recover,就会因为抛异常走到Failure分支
    f2 onComplete {
      case Success(value) => println(value)
      case Failure(exception) => println("ERR>>>", exception.getMessage)
    }
    
    // 简化写法
    val f3 = f1.map((f1_v: Int) => {
      if (f1_v > 1000) {
        "success and do something..."
      } else {
        throw new Exception("user defined exception...")
      }
    }).recover({
      case throwable: Throwable => throwable.getMessage
    })
    
    // 如果没有recover,就会因为抛异常走到Failure分支
    f3 onComplete {
      case Success(value) => println(value)
      case Failure(exception) => println("ERR>>>", exception.getMessage)
    }
    

    recoverWith

    val f1 = Future {
      throw new Exception("user defined exception...")
      Random.nextInt(10000)
    }
    
    val f2 = f1.recoverWith(new PartialFunction[Throwable, Future[String]] {
      override def isDefinedAt(x: Throwable): Boolean = x.getMessage.contains("user defined")
      override def apply(v1: Throwable): Future[String] = Future {
        v1.getMessage
      }
    })
    
    // 这里仍然会走success分支
    f2 onComplete {
      case Success(value) => println(value)
      case Failure(exception) => println("ERR>>>", exception.getMessage)
    }
    
    // 简化写法
    val f3 = f1.recoverWith({
      case throwable: Throwable => Future {
        throwable.getMessage
      }
    })
    
    // 这里仍然会走success分支
    f3 onComplete {
      case Success(value) => println(value)
      case Failure(exception) => println("ERR>>>", exception.getMessage)
    }
    

    andThen

    经andThen返回的新Future无论原Future成功或失败都会返回与原Future一模一样的结果。

    val f1 = Future {
      throw new Exception("user defined exception...")
      Random.nextInt(10000)
    }
    
    val f2 = f1.andThen(new PartialFunction[Try[Int], String] {
      override def isDefinedAt(x: Try[Int]): Boolean = x.isSuccess
    
      override def apply(v1: Try[Int]): String = {
        println("andThen run", "do something...")
        "do something..."
      }
    })
    
    // andThen正常执行,但这里会走Failure分支(返回原Future的结果)
    f2 onComplete {
      case Success(value) => println(value)
      case Failure(exception) => println("ERR>>>", exception.getMessage)
    }
    
    // 简化写法
    val f3 = f1.andThen({
      case i: Try[Int] => {
        println("andThen run", "do something...")
        "do something..."
      }
    })
    
    // andThen正常执行,但这里会走Failure分支(返回原Future的结果)
    f3 onComplete {
      case Success(value) => println(value)
      case Failure(exception) => println("ERR>>>", exception.getMessage)
    }
    

    投影(Projections)

    如果原future对象失败了,失败的投影(projection)会返回一个带有Throwable类型返回值的future对象。如果原Future成功了,失败的投影(projection)会抛出一个NoSuchElementException异常。
    这个看不懂有什么用-_-||

    // 会打印异常
    val f = Future {
      2 / 0
    }
    for (exc <- f.failed) println(exc)
    
    // 不会打印异常
    val f = Future {
      2 / 1
    }
    for (exc <- f.failed) println(exc)
    

    Promises(futures也可以使用promises来创建)

    W3C上没看到的

    // type相当于声明一个类型别名,下面把String类型用S代替,通常type用于声明某种复杂类型,或用于定义一个抽象类型。
    type S = String
    // Session => Validation[T]声明一个函数类型,参数是Session返回值是Validation[T]
    type Expression[T] = Session => Validation[T]
    
    // 自身类型(self type),格式:this: T =>
    // this也可替换为self或其它不是关键字的别名。
    // 作用:指定可以混入的类的超类。这个特质只能混入给定类型的子类中。(只有AA的子类可以混入A)
    // 注:特质extends一个类时,可以保证其混入的类都是该类的子类;而特质指定自身类型时,可以保证它只能混入该类的子类。
    trait A { 
      this: AA =>
    }
    
    // class中的自身类型让类抽象了-该类在实例化时必须满足AA;相当于构造一个复合类型(A with AA)。
    class A {
      this: AA =>
    }
    
    // 自身类型声明为复合类型:
    this: X with Y with Z => 
    
    // 自身类型声明为结构类型:
    this: { def close: Unit } => 
    
    // this 别名,可以用除关键字之外的所有字段,不一定要是self
    class A { 
      self =>  // this alisa
      val x = 2 
      def foo = self.x + this.x 
    }
    
    // sealed用来保证在使用match的时候需要把所有可能出现的情况都写出来,如果漏掉一个,就会编译出错
    sealed trait A {}
    class A1 extends A {}
    class A2 extends A {}
    class A3 extends A {}
    
    // a 没有任何修饰符,不是A的成员变量,只是一个构造方法的参数
    // b val修饰的变量,是A的成员变量,默认生成get方法
    // c var修饰的变量,是A的成员变量,默认生成get和set方法
    class A (a: Int, val b: Int, var c: Int) {}
    

    Scala中的"->"和"<-"以及"=>"

    转自

    ->

    // ->只会出现在k->v里面
    val map: Map[String, Any] = Map("name" -> "zhangsan", "age" -> 12, "from" -> "china")
    

    <-

    // <-只会出现在for循环里面
    val map: Map[String, Any] = Map("name" -> "zhangsan", "age" -> 12, "from" -> "china")
    for ((key, value) <- map) {
        println(key, value)
    }
    

    =>

    // 用法一:
    type t1 = Int => Int // t1 是一个函数类型(多用来在参数中表示需要传入一个函数,其类型需符合 t1)
    
    // 用法二:匿名函数
    val t2: t1 = (i: Int) => i * i // t2 是一个匿名函数(本身就是一个函数,可以执行的)
    
    // 用法三
    // 放在 case 后面,略
    
    // 用法四:By-Name Parameters(传名参数)
    // 传名参数在函数调用前表达式不会被求值,而是会被包裹成一个匿名函数作为函数参数传递下去
    def test_1(i: => Int): Int = { // 如果传入的值是一个普通的 Int ,则没有什么区别,如果传入的值是一个函数,则传入的函数不会立即执行,如下示例:
      println("run test_1")
      i * i
    }
    def test_2(i: Int): Int = {
      println("run test_2")
      i * i
    }
    test_1(test_2(3))
    
    > 执行顺序如下
    > run test_1
    > run test_2
    > run test_2
    
  • 相关阅读:
    ExecuteScalar requires the command to have a transaction when the connection assigned to the command is in a pending
    如何从vss中分离程序
    String or binary data would be truncated
    the pop3 service failed to retrieve authentication type and cannot continue
    The POP3 service failed to start because
    IIS Error he system cannot find the file specified _找不到页面
    pku2575Jolly Jumpers
    pku2940Wine Trading in Gergovia
    pku3219二项式系数
    pku1029false coin
  • 原文地址:https://www.cnblogs.com/CSunShine/p/11976474.html
Copyright © 2011-2022 走看看