大数据入门第二十天——scala入门(二)scala基础02
一、 类、对象、继承、特质
1.类
Scala的类与Java、C++的类比起来更简洁
定义:
- package com.jiangbei
- //在Scala中,类并不用声明为public。
- //Scala源文件中可以包含多个类,所有这些类都具有公有可见性。
- class Person {
- // 定义一个不可变的val(只有getter)和可变的var(getter setter都有)
- // 更直观的理解,可以通过反编译工具打开out目录的.class文件
- val id = 9527
- var name = "唐伯虎"
- }
当然,变量和Java一样可以进行访问控制:
- //类私有字段,只能在类的内部使用
- private var name: String = "唐伯虎"
//对象私有字段,访问权限更加严格的,Person类的方法只能访问到当前对象的字段
private[this] val pet = "小强"
构造器:
- package com.jiangbei
- /**
- *每个类都有主构造器,主构造器的参数直接放置类名后面,与类交织在一起
- * 注意:主构造器会执行类定义中的所有语句
- * 如果主构造器中的参数没有加val var等,则为private,无法外部访问
- * 构造器参数可以不带val或var,如果不带val或var的参数至少被一个方法所使用,那么它将会被提升为字段
- * //在类名后面加private就变成了私有的
- class Queen private(val name: String, prop: Array[String], private var age: Int = 18){
- *
- */
- class Person(var age: Int, name: String) {
- private var gender = "love"
- //用this关键字定义辅助构造器
- def this(name: String, age: Int, gender: String){
- //每个辅助构造器必须以主构造器或其他的辅助构造器的调用开始
- this(age, name)
- println("执行辅助构造器")
- this.gender = gender
- }
- }
- object Person{
- def main(args: Array[String]): Unit = {
- val p1 = new Person(18, "SMD")
- println(p1.age)
- // println(p1.name)
- }
- }
2.对象
单例对象
在Scala中没有静态方法和静态字段,但是可以使用object这个语法结构来达到同样的目的
1.存放工具方法和常量
2.高效共享单个不可变的实例
3.单例模式
- package com.jiangbei
- object Singleton {
- // object中定义的方法变量的都是静态的(静态方法、静态块)
- def main(args: Array[String]): Unit = {
- val s = Singleton
- println(s) // com.jiangbei.Singleton$@5e025e70
- }
- }
伴生对象
在Scala的类中,与类名相同的对象叫做伴生对象,类和伴生对象之间可以相互访问私有的方法和属性
一般伴生对象和类写在一个文件
- class Person(var age: Int, name: String) {
- private var gender = "love"
- }
- object Person{
- def main(args: Array[String]): Unit = {
- val p1 = new Person(18, "SMD")
- println(p1.gender)
- }
- }
apply方法
通常我们会在类的伴生对象中定义apply方法,当遇到类名(参数1,...参数n)时apply方法会被调用
- class Person() {
- }
- object Person{
- def apply():Unit = {
- println("apply被调用!")
- }
- def apply(name: String):Unit = {
- println(name)
- }
- def main(args: Array[String]): Unit = {
- // 以下的Person()会自动调用对应的无参的apply()方法,这里的p1就是返回值了。
- // 如果有多个,则对应参数相应的
- val p1 = Person()
- val p2 = Person("小强")
- }
- }
- 结果:
- apply被调用!
- 小强
应用程序对象
Scala程序都必须从一个对象的main方法开始,可以通过扩展App特质,不写main方法。(意义不大,不常用)
- object AppObjectDemo extends App{
- //不用写main方法
- println("I love you Scala")
- }
3.继承
继承:与Java保持一致,使用extands,实现接口使用with(with Flyable with Human)
重写:使用override修饰符
类型转换和类型检查:
Scala |
Java |
obj.isInstanceOf[C] |
obj instanceof C |
obj.asInstanceOf[C] |
(C)obj |
classOf[C] |
C.class |
实例:
- package com.jiangbei
- object Singleton {
- // object中定义的方法变量的都是静态的(静态方法、静态块)
- def main(args: Array[String]): Unit = {
- val b1 = new Bird
- b1.run()
- b1.flight()
- }
- }
- // 相当于Java8的接口,可以有默认实现
- trait Flyable {
- def fly(name: String): Unit = {
- println(name + " can fly!")
- }
- // 未实现方法
- def flight(): Unit
- }
- abstract class Animal {
- val name: String
- def run(): Unit
- }
- class Bird extends Animal with Flyable {
- override val name: String = "love"
- override def run(): Unit = {
- println("bird run!")
- }
- override def flight(): Unit = {
- println("bird flight")
- }
- }
// 详细待更新
二、模式匹配和样例类
Scala有一个十分强大的模式匹配机制,可以应用到很多场合:如switch语句、类型检查等。
并且Scala还提供了样例类,对模式匹配进行了优化,可以快速进行匹配
一个模式匹配包含了一系列备选项,每个都开始于关键字 case。每个备选项都包含了一个模式及一到多个表达式。箭头符号 =>隔开了模式和表达式。
1.字符串匹配
- def main(args: Array[String]): Unit = {
- val colors = Array("red", "green", "blue")
- val color = colors(Random.nextInt(colors.length))
- println("给你点颜色看看..")
- color match {
- case "blue" => println("蓝色")
- case "green" => println("绿色")
- case "red" => println("红色")
- case _ => println("不知道你在说什么..")
- }
- }
2.类型匹配
- def main(args: Array[String]): Unit = {
- val colors = Array("red", 1, 3.0)
- val color = colors(Random.nextInt(colors.length))
- println("给你点颜色看看..")
- color match {
- case x: String => println(x)
- case y: Int if y > 0 => println("大于0的整型")
- case Double => println("双精度浮点型")
- case _ => throw new Exception("类型不匹配!")
- }
- }
3.数组、元组匹配
- def main(args: Array[String]): Unit = {
- val arr = Array(1, 2 ,3)
- arr match {
- case Array(1, x, y) => println(x)
- case Array(0) => println("0")
- // 1开头的,后面任意
- case Array(1, _*) => println("0...")
- case _ => throw new Exception("类型不匹配!")
- }
- val lst = List(3, -1)
- lst match {
- case 0 :: Nil => println("only 0")
- case x :: y :: Nil => println(s"x: $x y: $y")
- case 0 :: tail => println("0 ...")
- case _ => println("something else")
- }
- val tup = (2, 3, 7)
- tup match {
- case (1, x, y) => println(s"1, $x , $y")
- case (_, z, 5) => println(z)
- case _ => println("else")
- }
- }
4.样例类
在Scala中样例类是一中特殊的类,可用于模式匹配。
case class是多例的,后面要跟构造参数,case object是单例的
- object ScalaDemo {
- def main(args: Array[String]): Unit = {
- val arr = Array(SubmitTask(1, "小强"), HeartBeat(1000), CheckTimeOutTask)
- arr(Random.nextInt(arr.length)) match {
- case SubmitTask(id, name) => println(s"$id,$name")
- case HeartBeat(t) => println(s"time:$t")
- case CheckTimeOutTask => println("CheckTimeOut!")
- }
- }
- }
- case class SubmitTask(id: Int, name: String)
- case class HeartBeat(time: Long)
- case object CheckTimeOutTask
5.Option类型
在Scala中Option类型样例类用来表示可能存在或也可能不存在的值(Option的子类有Some和None)。
Some包装了某个值,None表示没有值(和Java8类似)
Option[T] 是一个类型为 T 的可选值的容器: 如果值存在, Option[T] 就是一个 Some[T] ,如果不存在, Option[T] 就是对象 None 。
当然,也可以使用getOrElse来控制默认值
- def main(args: Array[String]): Unit = {
- val myMap = Map("color" -> "blue")
- // get返回的就是一个option类型
- val v1: Option[String] = myMap.get("color")
- val v2: Option[String] = myMap.get("price")
- println(v1)// Some(blue)
- println(v2)// None
- }
6.偏函数
被包在花括号内没有match的一组case语句是一个偏函数,
它是PartialFunction[A, B]的一个实例,A代表参数类型,B代表返回类型,常用作输入模式匹配
- def func1: PartialFunction[String, Int] = {
- case "one" => 1
- case "two" => 2
- case _ => -1
- }
后面调用的时候可以根据传入的值进行匹配,从而返回不同的值
更多基础相关,参考:https://www.cnblogs.com/wjcx-sqh/p/6551248.html
三、高阶函数和隐式转换
1.高阶函数
Scala混合了面向对象和函数式的特性,我们通常将可以做为参数传递到方法中的表达式叫做函数。
在函数式编程语言中,函数是“头等公民”,高阶函数包含:作为值的函数、匿名函数、闭包、柯里化等等。
作为值的函数
- val fun = (x: Int) => x * 2
- arr.map(fun)
匿名函数
- arr.map(x => x * 2) // 可以省略类型
arr.map(_ * 2) // 可以使用神奇的下划线代表当前变量,更加简洁!,也可以使用 m1 _来将方法转换为函数
柯理化
柯里化指的是将原来接受两个参数的方法变成新的接受一个参数的方法的过程
导言:
- // 定义一个方法,不过形式上看起来有点像函数
- def m(x: Int) = (y:Int)=> x * y
- // 给它传一个值,就变成了函数
- val fun = m(2) // fun = (y:Int) => 2 * y
- // 调用这个函数
- fun(5) //值为10
- // 一步到位,就变成了
- m(2)(5)
- // 这就得到了柯理化:
- def m(x:Int)(y:Int) = x * y
// 可以只传一个参数:m(3)(_)
- def main(args: Array[String]) {
- def f2(x: Int) = x * 2
- val f3 = (x: Int) => x * 3
- val f4: (Int) => Int = { x => x * 4 }
- val f4a: (Int) => Int = _ * 4
- val f5 = (_: Int) * 5
- val list = List(1, 2, 3, 4, 5)
- var new_list: List[Int] = null
- //第一种:最直观的方式 (Int) => Int
- //new_list = list.map((x: Int) => x * 3)
- //第二种:由于map方法知道你会传入一个类型为(Int) => Int的函数,你可以简写
- //new_list = list.map((x) => x * 3)
- //第三种:对于只有一个参数的函数,你可以省去参数外围的()
- //new_list = list.map(x => x * 3)
- //第四种:(终极方式)如果参数在=>右侧只出现一次,可以使用_
- new_list = list.map(_ * 3)
- new_list.foreach(println(_))
- var a = Array(1,2,3)
- a.map(_* 3)
- }
柯理化示例
2.隐式转换
简单说,隐式转换就是:当Scala编译器进行类型匹配时,如果找不到合适的候选,那么隐式转化提供了另外一种途径来告诉编译器如何将当前的类型转换成预期类型。
通过隐式转换,程序员可以在编写Scala程序时故意漏掉一些信息,让编译器去尝试在编译期间自动推导出这些信息来。
隐式的对类的方法进行增强,丰富现有类库的功能
那种以implicit关键字声明的带有单个参数的函数称为隐式转换函数
示例1:
- import java.io.File
- import scala.io.Source
- //隐式的增强File类的方法
- class RichFile(val from: File) {
- def read = Source.fromFile(from.getPath).mkString
- }
- object RichFile {
- //隐式转换方法
- implicit def file2RichFile(from: File) = new RichFile(from)
- }
- object MainApp{
- def main(args: Array[String]): Unit = {
- //导入隐式转换
- import RichFile._
- //import RichFile.file2RichFile
- println(new File("c://words.txt").read)
- }
- }
示例2:
- import java.awt.GridLayout
- /**
- * Created by ZX on 2015/11/13.
- */
- object ImplicitContext{
- //implicit def girl2Ordered(g : Girl) = new Ordered[Girl]{
- // override def compare(that: Girl): Int = if (g.faceValue > that.faceValue) 1 else -1
- //}
- implicit object OrderingGirl extends Ordering[Girl]{
- override def compare(x: Girl, y: Girl): Int = if (x.faceValue > y.faceValue) 1 else -1
- }
- }
- class Girl(var name: String, var faceValue: Double){
- override def toString: String = s"name : $name, faveValue : $faceValue"
- }
- //class MissRight[T <% Ordered[T]](f: T, s: T){
- // def choose() = if(f > s) f else s
- //}
- //class MissRight[T](f: T, s: T){
- // def choose()(implicit ord: T => Ordered[T]) = if (f > s) f else s
- //}
- class MissRight[T: Ordering](val f: T, val s: T){
- def choose()(implicit ord: Ordering[T]) = if(ord.gt(f, s)) f else s
- }
- object MissRight {
- def main(args: Array[String]) {
- import ImplicitContext.OrderingGirl
- val g1 = new Girl("yuihatano", 99)
- val g2 = new Girl("jzmb", 98)
- val mr = new MissRight(g1, g2)
- val result = mr.choose()
- println(result)
- }
- }
大数据入门第二十天——scala入门(二)scala基础02的更多相关文章
- 大数据入门第二十天——scala入门(一)入门与配置
一.概述 1.什么是scala Scala是一种多范式的编程语言,其设计的初衷是要集成面向对象编程和函数式编程的各种特性.Scala运行于Java平台(Java虚拟机),并兼容现有的Java程序. ...
- 大数据入门第二十天——scala入门(二)scala基础01
一.基础语法 1.变量类型 // 上表中列出的数据类型都是对象,也就是说scala没有java中的原生类型.在scala是可以对数字等基础类型调用方法的. 2.变量声明——能用val的尽量使用val! ...
- 大数据入门第十二天——sqoop入门
一.概述 1.sqoop是什么 从其官网:http://sqoop.apache.org/ Apache Sqoop(TM) is a tool designed for efficiently tr ...
- 大数据入门第十二天——azkaban入门
一.概述 1.azkaban是什么 通过官方文档:https://azkaban.github.io/ Azkaban is a batch workflow job scheduler create ...
- 大数据入门第十二天——flume入门
一.概述 1.什么是flume 官网的介绍:http://flume.apache.org/ Flume is a distributed, reliable, and available servi ...
- 大数据入门第二十一天——scala入门(一)并发编程Actor
注:我们现在学的Scala Actor是scala 2.10.x版本及以前版本的Actor. Scala在2.11.x版本中将Akka加入其中,作为其默认的Actor,老版本的Actor已经废弃 一. ...
- 大数据入门第十九天——推荐系统与mahout(一)入门与概述
一.推荐系统概述 为了解决信息过载和用户无明确需求的问题,找到用户感兴趣的物品,才有了个性化推荐系统.其实,解决信息过载的问题,代表性的解决方案是分类目录和搜索引擎,如hao123,电商首页的分类目录 ...
- 大数据入门第十七天——storm上游数据源 之kafka详解(一)入门与集群安装
一.概述 1.kafka是什么 根据标题可以有个概念:kafka是storm的上游数据源之一,也是一对经典的组合,就像郭德纲和于谦 根据官网:http://kafka.apache.org/intro ...
- 大数据入门第十一天——hive详解(一)入门与安装
一.基本概念 1.什么是hive The Apache Hive ™ data warehouse software facilitates reading, writing, and managin ...
随机推荐
- jQuery操作table数据上移、下移和置顶
jQuery 操作table中的tr换行的步骤如下: 1.获取当前tr var $tr = $(this).parents("tr"); 2.移动tr //上移 $tr.prev( ...
- 前端开发笔记(2)css基础(上)
CSS介绍 层叠样式表(英文全称:Cascading Style Sheets)是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言.CSS ...
- JavaScript写计算器
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 如何用 Python 实现 Web 抓取?
[编者按]本文作者为 Blog Bowl 联合创始人 Shaumik Daityari,主要介绍 Web 抓取技术的基本实现原理和方法.文章系国内 ITOM 管理平台 OneAPM 编译呈现,以下为正 ...
- PHP多进程编程之僵尸进程问题
上一篇说到了使用pcntl_fork函数可以让PHP实现多进程并发或者异步处理的效果.那么问题是我们产生的进程需要去控制,而不能置之不理.最基本的方式就是fork进程和杀死进程. 通过利用pcntl_ ...
- Jboss 4.2.3配置与优化
1 Jboss内存优化 修改这个两参数,给jvm分配适当的内存,一般为服务器的3/4内存量,推荐至少使用4G内存. 另外添加两个参数 -XX:+UseParallelGC -XX:+UseP ...
- vscode 折叠所有区域代码的快捷键
折叠:ctrl + L ctrl + 0(主键盘区的0,不是小键盘区的0) 展开:ctrl + K ctrl + J 老是忘记,在此记录
- Python学习--Selenium模块
1. Python学习--Selenium模块介绍(1) 2.Python学习--Selenium模块学习(2) 其他: 1. Python学习--打码平台
- load data infile出现“ERROR 13 (HY000): Can't get stat of '/tmp/test2.txt' (Errcode: 2)”问题
用load data infile导数据到mysql数据库出现这个该问题,解决方法如下: 安全起见,连接mysql的语句需要添加–local-infile, mysql -hlocalhost -ur ...
- 【Python】os.path.isfile()的使用方法汇总
方法一: # -*- coding:utf-8 -*- import os import sys from uiautomator import device as d filepath = r'E: ...