大数据入门第二十天——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 ...
随机推荐
- JS 解决 IOS 中拍照图片预览旋转 90度 BUG
上篇博文[ Js利用Canvas实现图片压缩 ]中做了图片压缩上传,但是在IOS真机测试的时候,发现图片预览的时候自动逆时针旋转了90度.对于这个bug,我完全不知道问题出在哪里,接下来就是面向百度编 ...
- 安卓测试【三】adb简单命令及monkey使用
Ⅰ 配置好android sdk环境变量之后,将android手机连接到电脑上,进行一些adb的简单命令的操作. adb,安卓调试桥,android sdk的一个工具.直接操作管理安卓模拟器或者真 ...
- Django 序列化三种方式 对象 列表 元组
1.xuliehua.html <html lang="en"> <head> <meta charset="UTF-8"> ...
- DevOps之基础设施-电力
唠叨话 关于噢屁事的知识点,仅提供精华汇总,具体知识点细节,参考教程网址,如需帮助,请留言. <基础设施-电力> 关于基础设施的电力部分,知识与技能的层次(知道.理解.运用),理论与实践的 ...
- python之绘制图形库turtle
关于绘制图形库turtle# 画布上,默认有一个坐标原点为画布中心的坐标轴(0,0),默认"standard"模式坐标原点上有一只面朝x轴正方向小乌龟 一:海龟箭头Turtle相关 ...
- JAVA JComboBox的监听事件(ActionListener、ItemListener)
版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 参考资料: http://263229365.iteye.com/blog/1040329 https://www.ja ...
- Hadoop 本地模式安装
0. 说明 本地模式:使用的存储系统,是Linux系统 提前安装好 JDK 参考 CentOS7 安装 JDK 1. 将 Hadoop 的安装包通过 Xftp 发送到centos 用户的 home 目 ...
- 正确计算linux系统内存使用率
参考:https://blog.gesha.net/archives/406/ 图中的例子很典型,就是:多数的linux系统在free命令后会发现free(剩余)的内存很少,而自己又没有开过多的程序或 ...
- if 和 elif 的区别
if: 如果一个判断中用if, 程序他会遍历所有的if, 即使你的判断条件遍历到了, 也会继续执行, 直到遍历完所有的if. elif: 而elif呢, 则效率很高. 只要遍历到你的判断条件, ...
- Beta阶段第五次冲刺
Beta阶段第五次冲刺 严格按照Git标准来,组员有上传Git的才有贡献分没有的为0 代码签入图 1.part1 -站立式会议照片 2.part2 -项目燃尽图 3.part3 -项目进展 1.正在进 ...