文章目录
scala 进阶
1.高阶函数
1.1 函数作为参数的函数
使用函数作为参数的方法,叫做高阶函数
package cn.itcast.scala
object ScalaTest {
val myFunc = (x:Int) => {
x*x}
def main(args: Array[String]): Unit = {
//方法就是函数,函数就是对象
def myMethod(x:Int) : Int = {
x*x}
val myArray0 = Array(1,3,5,7,9).map(x => x*x) //匿名函数优先使用
val myArray1 = Array(1,3,5,7,9).map(myFunc) //函数就是对象
val myArray2 = Array(1,3,5,7,9).map(myMethod) //方法就是函数
val myArray3 = Array(1,3,5,7,9).map(_*2) //实现不了x*x功能 因为x出现了两次,不能使用_
println(myArray0.mkString(","))
println(myArray1.mkString(","))
println(myArray2.mkString(","))
println(myArray3.mkString(","))
}
}
1.2 匿名函数
package cn.itcast.scala
object ScalaTest {
def main(args: Array[String]): Unit = {
println((x:Int,y:Int) => {
x * y}) // <function2>
}
}
1.3 高阶函数
package cn.itcast.scala
object ScalaTest {
def main(args: Array[String]): Unit = {
val func3: (String, Int) => (Int, String) = {
(x, y) => (y + 2, x + "hello")
}
//函数匿名函数定义第二种方式
def myMethod3(hello: (String, Int) => (Int, String)): Int = {
val result: (Int, String) = hello("zhangsan", 60)
result._1
}
val result: Int = myMethod3(func3)
println(result) //62
}
}
1.4 高阶函数作为方法的返回类型
package cn.itcast.scala
object ScalaTest {
def main(args: Array[String]): Unit = {
def myFunc4(x:Int) = {
//方法的最后返回值,是一个匿名函数
(y:String) =>y + x
}
println(myFunc4(50)) //<function1>
}
}
1.5 参数类型推断
package cn.itcast.scala
object ScalaTest {
def main(args: Array[String]): Unit = {
val myArray = Array(1, 3, 5, 7, 9)
//map当中需要传入一个函数,我们可以直接定义一个函数
println(myArray.map((x: Int) => x * 2).mkString("==="))
//进一步化简 参数推断省去类型信息
println(myArray.map((x) => x * 2).mkString("==="))
//进一步化简 单个参数可以省去括号
println(myArray.map(x => x * 2).mkString("==="))
///进一步化简 如果变量只在=>右边只出现一次,可以用_来代替
println(myArray.map(_ * 2).mkString("==="))
/*
2===6===10===14===18
2===6===10===14===18
2===6===10===14===18
2===6===10===14===18
*\
}
}
1.6 闭包与柯里化
package cn.itcast.scala
object ScalaTest {
def main(args: Array[String]): Unit = {
//柯里化 柯里化定义形式
def kery(x:Int)(y:Int) = {
x+y
}
val kery1: Int = kery(30)(20)
println(kery1)
val keryResult = (x:Int) => {
(y:Int) => {
x + y} } // 函数的返回值也是函数,为function1,切内部是匿名函数无法赋值
println(keryResult(10))
//keryResult(20) => 匿名函数 y:Int => 20+y <=1,3,5,7,9
val myArray = Array(1,3,5,7,9).map(keryResult(20))
println(myArray.toBuffer) //ArrayBuffer(21, 23, 25, 27, 29)
//柯里化推导过程
//柯里化守门Scala面向函数式编程,必然导致的一种结果
def keryMethod(x:Int) = {
//里面的函数,将外面的参数包起来了,叫做闭包
y:Int => {
y + x}
}
keryMethod(30)
}
}
总结:
函数可以用来干嘛 ==>
1.作为一个方法的参数
2.函数可以直接调用
3.匿名函数无法调用,但是可以通过作为一个方法的参数进行赋值调用如
Array(1,3,5,7,9).map(keryResult(20))
2.scala当中的类
2.1 类的定义与创建
package cn.itcast.scala
class Person {
//定义一个属性,叫做name的,使用val不可变量来进行修饰
// 用val修饰的变量是可读属性,有getter但没有setter(相当与Java中用final修饰的变量)自动生成该方法
val name:String ="zhangsan"
//定义一个属性,叫做age的,使用var可变量来进行修饰
//用var修饰的变量都既有getter,又有setter 自动生成该方法
var age:Int = 28
//类私有字段,只能在类的内部使用或者伴生对象中访问
private val address:String = "地球上"
//类私有字段,访问权限更加严格的,该字段在当前类中被访问
//在伴生对象里面也不可以访问
private[this] var pet = "小强"
//在类当中定义了一个方法,
def hello(first:Int,second:String):Int ={
println(first+"\t"+second)
250
}
/**
* 定义了一个函数
*/
val func1 =(x:Int,y:Int) =>{
x+y
}
}
2.2 类的实例化以及使用
package cn.itcast.scala
object ScalaClass {
def main(args: Array[String]): Unit = {
val person = new Person
val name: String = person.name
val age: Int = person.age
println(name)
println(age)
person.age = (30) // 这个是赋值操作
person.age= (30) // age= 这个是set方法,.age=连起来写
person.age_= (80) // age_= 这个是set方法
println(person.age) //这个是get方法
//调用函数或者方法
val hello: Int = person.hello(120,"zhangsan")
println(hello) //250
}
}
2.3 属性的getter和setter方法
对于scala类中的每一个属性,编译后,会有一个私有的字段和相应的getter、setter方法生成
//getter方法
println(person age)
//setter方法
println(person age_= (18))
//getter方法
println(person.age)
当然了,你也可以不使用自动生成的方式,自己定义getter和setter方法
class Dog2 {
private var _leg = 4
def leg = _leg
def leg_=(newLeg: Int) {
_leg = newLeg
}
}
使用之:
val dog2 = new Dog2
dog2.leg_=(10)
println(dog2.leg)
规范提示:自己手动创建变量的getter和setter方法需要遵循以下原则:
1) 字段属性名以“_”作为前缀,如:_leg
2) getter方法定义为:def leg = _leg
3) setter方法定义时,方法名为属性名去掉前缀,并加上后缀,后缀是:“leg_=”,如例子所示
2.4 类的构造器
scala当中类的构造器分为两种:主构造器和辅助构造器
主构造器,写在类名后面的。
所有的辅助构造器,在最后都必须调用另外一个构造器
java中构造器
public class Dog{
public Dog(String name,int age){
System.out.println("xxxx")
}
}
new Dog("小黑",3)
scala中构造器
package cn.itcast.scala
/**
* 顶一个class类,主构造器带有两个参数,name与age
*
* @param name
* @param age
* scala的执行代码,可以直接将代码写在class当中,而在java当中不能
* 在Scala编译之后成为.class文件
* 将我们所有class类的代码都进入到了主构造器方法当中去了
* class Dog{
* public Dog(String name,int age){
* println(name)
* println(age)
* }
* }
*/
class Dog(name: String, age: Int) {
println(name)
println(age)
var gender: String = "";
//使用this关键字来定义我们的构造器
def this(name: String, age: Int, gender: String) {
//每个辅助构造器,都必须以其他辅助构造器,或者主构造器的调用作为第一句
this(name: String, age: Int)
this.gender = gender
}
var color = "";
/**
* 我们也可以通过private来进行修饰我们的构造器,
*
* @param name
* @param age
* @param color
* @param gender
*/
private def this(name: String, age: Int, color: String, gender: String) {
this(name: String, age: Int)
this.color = color
}
}
两个构造器之间不能相互调用
Object通过构造器生成对象
package cn.itcast.scala
object ScalaClass {
def main(args: Array[String]): Unit = {
val xiaoheigou: Dog = new Dog("xiaoheigou",3)
val xiaobaigou: Dog = new Dog("xiaobaigou",2,"cixing")
}
}
3.scala当中的对象
Java中
public class MyClass{
public static String name="xxx"
public String age = "xxx"
public static String getMyAge(){
return "xxx"
}
public int getMyRealAge(){
return 1;
}
}
Scala中
将static和非static的东西全部分开
object 里面装的东西,可以简单的认为,全部都是static修饰的
class里面装的东西,可以简单的任务,全部都是没有static修饰的(需要new对象)
3.1 scala当中的Object
定义一个class类,然后在class类当中定义一个Object的对象。object对象当中的所有属性或者方法都是静态的
class Session {
def hello(first:Int):Int={
println(first)
first
}
}
object SessionFactory{
val session = new Session
def getSession():Session ={
session
}
def main(args: Array[String]): Unit = {
for(x <- 1 to 10){
//通过直接调用,产生的对象都是单列的
val session = SessionFactory.getSession()
println(session)
}
}
}
3.2 伴生类与伴生对象
特点:
1.如果有一个class文件,还有一个与class同名的object文件,那么就称这个object是class的伴生对象,
class是object的伴生类;
2.伴生类和伴生对象必须存放在一个.scala文件中;
3.伴生类和伴生对象的最大特点是,可以相互访问;
package cn.itcast.scala
class ClassObject {
val id = 1
private var name = "itcast"
def printName(): Unit ={
//在Dog类中可以访问伴生对象Dog的私有属性
println(ClassObject.CONSTANT + name )
}
}
object ClassObject{
//伴生对象中的私有属性
private val CONSTANT = "汪汪汪 : "
def main(args: Array[String]) {
val p = new ClassObject
//访问私有的字段name
p.name = "123"
p.printName()
}
}
3.3 scala当中的apply方法
通过apply方法来创建我们的伴生类,可以通过伴生对象来创建我们的伴生类,更加简洁和方便
package cn.itcast.scala
//定义一个class类,主构造器传入一个参数
class ApplyClassObject(name:String) {
println(name)
}
object ApplyClassObject{
def apply(name: String): ApplyClassObject = new ApplyClassObject(name)
def main(args: Array[String]): Unit = {
val applyClassObject1 = new ApplyClassObject("张三")
//通过伴生对象,直接调用调用apply方法,来获取我们的一个伴生类
val applyClassObject2 = ApplyClassObject("lisi")
//底层还是调用了apply方法,apply还是new Array[Int](5)
val myArray = Array(1,2,3,4,5)
val myArray2 = new Array[Int](10)
myArray2(0)=1
myArray2(1)=2
}
}
3.4 scala当中的main方法
//1.在object中定义main方法
object Main_Demo1 {
def main(args: Array[String]) {
if(args.length > 0){
println("Hello, " + args(0))
}else{
println("Hello World1!")
}
}
}
//2.使用继承App Trait ,将需要写在 main 方法中运行的代码
// 直接作为 object 的 constructor 代码即可,
// 而且还可以使用 args 接收传入的参数。
object Main_Demo2 extends App{
if(args.length > 0){
println("Hello, " + args(0))
}else{
println("Hello World2!")
}
}
3.5 枚举
java
public enum{
HELLO,ABC,123
}
enum.HELLO
public static String CONSTANTS = "HELLO"
Scala中没有枚举类型,但是我们可以通过定义一个扩展Enumeration类的对象,并以value调用初始化枚举中的所有可能值:
4.scala当中的继 承
4.1 Scala中继承(extends)的概念
ackage cn.itcast.extends_demo
class Person {
val name="super"
def getName=this.name
}
class Student extends Person{
//继承加上关键字
override
val name="sub"
//重写方法
override def getName = "xxx"
//子类可以定义自己的field和method
val score="A"
def getScore=this.score
}
4.2 Scala中override 和 super 关键字
class Person1 {
private val name = "leo"
val age=50
def getName = this.name
}
class Student1 extends Person1{
private val score = "A"
//子类可以覆盖父类的 val field,使用override关键字
override
val age=30
def getScore = this.score
//覆盖父类非抽象方法,必须要使用 override 关键字
//同时调用父类的方法,使用super关键字
override def getName = "your name is " + super.getName
}
4.3 Scala中isInstanceOf 和 asInstanceOf
Class B extends Class A
Class C
B instanceOf A => 如果判断 B是A的子类 (A)B
C instanceOf A ==> 如果判断 C不是A的子类 不能强转
java当中只提供了子类判断是否属于父类形 instanceOf,没有提供判断一个类是否是另外一个类的父类的方法
isInstanceOf 和 asInstanceOf
isInstanceOf ==> 类似于java当中的instanceOf 做类型判断的
如果 判断 A isInstanceOf B 为true
可以调用 A asInstanceOf B 做类型转换
asInstanceOf ==> 做类型转换的
package cn.itcast.extends_demo
class Person3 {
}
class Student3 extends Person3
object Student3{
def main (args: Array[String] ) {
val p: Person3 = new Student3
var s: Student3 = null
//如果对象是 null,则 isInstanceOf 一定返回 false
println (s.isInstanceOf[Student3])
// 判断 p 是否为 Student3 对象的实例
if (p.isInstanceOf[Student3] ) {
//把 p 转换成 Student3 对象的实例
s = p.asInstanceOf[Student3]
}
println (s.isInstanceOf[Student3] )
}
}
4.4 Scala中getClass 和 classOf
传入一个Any 是不是Array 这一个确定的类型
package cn.itcast.extends_demo
class Person4 {
}
class Student4 extends Person4
object Student4{
def main(args: Array[String]) {
<