Scala--隐式转换、读取文件及控制台数据、泛型

1. 隐式转换

1.1 两个类之间的隐式转换
  • 在日常工作中,在引用其他 jar 的时候,可能会出现当前 jar 不能满足当前的业务需求,希望开发一些新的 API 来进行操作,如果是自己公司开发的 jar 还好,但是可能会遇到无法修改的 jar,这时候可以使用 Scala 中的隐式转换。

  • 两个类之前的隐式转换,我们可以理解成 简单的类转换成了加强的类,加强的类不仅有简单的类的功能,还可以额外增加一些符合当前业务场景的 API。

  • 隐式转换用的好,有利于开发,每个东西都有两面性,隐式转换用的不好,则会导致后期很难维护。

  • 需求:

    • 定义 Person 、SuperPerson 类,通过隐式转换使 Person 可以使用 SuperPerson里面的方法
  • 做法:

    • 第一步:先定义两个类:Person、SuperPerson
    • 第二步:使用 implicit 关键词,强化 Person 类,使 Person 具有 SuperPerson 类的属性和方法
    • 第三步:调用 Person 类
  • ImplicitUtils

package com.xk.bigdata.scala.imp

import com.xk.bigdata.scala.imp.ImplicitClass.{Person, SuperPerson}

object ImplicitUtils {

  implicit def person2SuperPerson(person: Person): SuperPerson = new SuperPerson(person.name)
}
  • ImplicitClass
package com.xk.bigdata.scala.imp

import com.xk.bigdata.scala.imp.ImplicitUtils._

/**
 * 需求:
 * 1. 定义 Person 、SuperPerson 类,通过隐式转换使 Person 可以使用 SuperPerson里面的方法
 */
object ImplicitClass {

  def main(args: Array[String]): Unit = {
    val person = new Person("spark")
    person.fly()
  }

  class Person(val name: String)

  class SuperPerson(val name: String) {
    def fly(): Unit = {
      println(s"$name is fly")
    }
  }

}
  • 需求:定义一个隐式转换的 SuperPerson2 类,直接 new 一个 Person 就可以使用 SuperPerson2 中的方法
package com.xk.bigdata.scala.imp

/**
 * 需求:
 * 1. 定义 Person 、SuperPerson 类,通过隐式转换使 Person 可以使用 SuperPerson里面的方法
 * 2. 定义一个隐式转换的 SuperPerson2 类,直接 new 一个 Person 就可以使用 SuperPerson2 中的方法
 */
object ImplicitClass {

  def main(args: Array[String]): Unit = {
    val person = new Person("spark")
    person.fly()
  }

  class Person(val name: String)

  class SuperPerson(val name: String) {
    def fly(): Unit = {
      println(s"$name is fly")
    }
  }

  implicit class SuperPerson2(val person: Person) {
    def fly(): Unit = {
      println(s"${person.name} is fly")
    }
  }

}
1.2 隐式参数
  • 需求:在含参方法中定义一个隐式参数,在调用的时候方法不需要传参数就可以直接使用该方法

  • 做法:

    • 第一步:定义一个含参数的方法
    • 第二步:定义一个隐式常量
    • 第三步:调用该方法
package com.xk.bigdata.scala.imp

/**
 * 隐式参数
 * 需求:在含参方法中定义一个隐式参数,在调用的时候方法不需要传参数就可以直接使用该方法
 */
object ImplicitParams {

  def main(args: Array[String]): Unit = {
    implicit val x = "spark"
    speak
  }

  def speak(implicit name: String): Unit = {
    println(s"$name is speak")
  }

}
1.3 隐式转换作用域
  • 隐式转换作用在:
    • 在调用隐式转换的代码作用域内部,并且要在调用隐式转换的代码之前
    • 相关类的伴生对象里面:在本例中相关类就是 Person、SuperPerson
package com.xk.bigdata.scala.imp

/**
 * 隐式转换的作用域
 */
object ImplicitScope {

  def main(args: Array[String]): Unit = {


    val person = new Person("hadoop")
    person.fly()
  }
}

class Person(val name: String)

class SuperPerson(val person: Person) {
  def fly(): Unit = {
    println(s"${person.name} is fly")
  }
}

object Person {
  implicit def richPerson(person: Person): SuperPerson = {
    println("隐式转换的作用域")
    new SuperPerson(person)
  }
}

object SuperPerson {

}

2. 读取文件数据

package com.xk.bigdata.scala.read

import scala.io.Source

/**
 * 读取文件数据
 */
object ReadFile {

  def main(args: Array[String]): Unit = {

    // 读取文件数据
    val words = Source.fromFile("data/wc.txt").getLines()
    while (words.hasNext){
      println(words.next())
    }

  }

}

3. 读取控制台数据

package com.xk.bigdata.scala.read

import java.io.{BufferedReader, InputStreamReader}
import java.util.Scanner

import scala.io.StdIn

/**
 * 读取控制台数据
 * 1. Java 读取控制台数据(字节流)
 * 2. Java 封装的读取控制台数据
 * 3. Scala 读取控制台数据
 */
object ReadConsole {

  def main(args: Array[String]): Unit = {

    // Java 读取控制台数据(字节流)
    val reader = new BufferedReader(new InputStreamReader(System.in))
    val data1 = reader.readLine()
    println(s"==========>$data1")

    // Java 封装的读取控制台数据
    val scanner = new Scanner(System.in)
    val data2 = scanner.next()
    println(s"==========>$data2")

    // Scala 读取控制台数据
    val data3 = StdIn.readLine()
    println(s"==========>$data3")

  }

}

4. 泛型

4.1 泛型的介绍
  • 泛型用于指定方法或类可以接受任意类型参数,参数在实际使用时才被确定,泛型可以有效地增强程序的适用性,使用泛型可以使得类或方法具有更强的通用性。泛型的典型应用场景是集合及集合中的方法参数,可以说同java一样,scala中泛型无处不在,具体可以查看scala的api。
  • 泛型类:指定类可以接受任意类型参数。
  • 泛型方法:指定方法可以接受任意类型参数。
4.1.1 定义泛型类
package com.xk.bigdata.scala.generic

/**
 * 泛型类
 */
object GenericClass {

  def main(args: Array[String]): Unit = {
    val message = new Message(11)
    message.loginfo()
  }

  /**
   * 定义一个任意类型的 msg ,通过实例化的时候传入
   */
  class Message[T](val msg: T) {
    def loginfo(): Unit = {
      println("=========>" + msg)
    }
  }

}
4.1.2 定义泛型方法
package com.xk.bigdata.scala.generic

/**
 * 定义泛型方法
 */
object GenericFunction {

  def main(args: Array[String]): Unit = {
    GenericFunctionTest().logingo("111")
    GenericFunctionTest().logingo(2222)
    GenericFunctionTest().logingo(3333L)
  }

  class GenericFunctionTest() {

    def logingo[T](msg: T): Unit = {
      println("=========>" + msg)
    }
    
  }

  object GenericFunctionTest {
    def apply(): GenericFunctionTest = new GenericFunctionTest()
  }
  
}
4.2 上界和下界
4.2.1 介绍
  • 在指定泛型类型时,有时需要界定泛型类型的范围,而不是接收任意类型。比如,要求某个泛型类型,必须是某个类的子类,这样在程序中就可以放心的调用父类的方法,程序才能正常的使用与运行。此时,就可以使用上下边界Bounds的特性。
  • Scala的上下边界特性允许泛型类型是某个类的子类,或者是某个类的父类。
    • S <: T 这是类型上界的定义,也就是S必须是类型T的子类(或本身,自己也可以认为是自己的子类)。
    • U >: T 这是类型下界的定义,也就是U必须是类型T的父类(或本身,自己也可以认为是自己的父类)。
4.2.2 上界示例
package com.xk.bigdata.scala.generic

/**
 * 上界示例
 */
object GenericUpBound {

  def logingo[T <: Student](msg: T): Unit = {
    println("=========>" + msg)
  }

  def main(args: Array[String]): Unit = {
    logingo[Student](new Student)
    logingo[Children](new Children)
  }

  class Person

  class Student extends Person

  class Children extends Student

}
4.2.3 下界示例
package com.xk.bigdata.scala.generic

/**
 * 下界示例
 */
object GenericDownBound {

  def logingo[T >: Student](msg: T): Unit = {
    println("=========>" + msg)
  }

  def main(args: Array[String]): Unit = {
    logingo[Person](new Person)
    logingo[Student](new Student)
  }

  class Person

  class Student extends Person

  class Children extends Student

}
4.3 协变和逆变
  • 对于一个带类型参数的类型,比如 List[T]:

    • 如果对A及其子类型B,满足 List[B]也符合 List[A]的子类型,那么就称为covariance(协变)。
    • 如果 List[A]是 List[B]的子类型,即与原来的父子关系正相反,则称为contravariance(逆变)。
  • 在声明Scala的泛型类型时,“+”表示协变,而“-”表示逆变。

    • C[+T]:如果A是B的子类,那么C[A]是C[B]的子类。
    • C[-T]:如果A是B的子类,那么C[B]是C[A]的子类。
    • C[T]:无论A和B是什么关系,C[A]和C[B]没有从属关系。
4.3.1 协变示例
package com.xk.bigdata.scala.generic

/**
 * 协变示例
 */
object GenericCovariant {

  def main(args: Array[String]): Unit = {
    new Message[Person](new Student).loginfo()
    new Message[Person](new Children).loginfo()
  }

  class Person

  class Student extends Person

  class Children extends Student

  class Message[+T](val msg: T) {
    def loginfo(): Unit = {
      println("=========>" + msg)
    }
  }

}
4.3.2 逆变示例
package com.xk.bigdata.scala.generic

/**
 * 逆变示例
 */
object GenericInversion {

  def main(args: Array[String]): Unit = {
    val student: Message1[Student1] = new Message1[Student1]()
    val child: Message1[Children1] = student
    println(child)
  }

  class Person1

  class Student1 extends Person1

  class Children1 extends Student1

  class Message1[-T]() {
  }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值