现在的位置: 首页 > 综合 > 正文

scala学习

2019年05月27日 ⁄ 综合 ⁄ 共 4597字 ⁄ 字号 评论关闭

(1)class 与 object的联系

singleton objects - scala中没有静态方法和属性,全部由singleton
object(单例对象)来替代
如果没有相对应的class,而是只有一个object的话,则称为stand-alone. object。在object中定义的内容如果为public,则对外开放,而相对的在class中定义的内容则必须在class被实例化是才可以被调用,另一方面的佐证:class可以定义构造参数,而相对的object则无法定义构造


(2)Trait

Trait有点类似于java中的interface,但也有不同之处:

①java的interface只定义方法名称和参数列表,不能定义方法体。而trait则可以定义方法体如:

<span style="font-size:14px;">trait Friendly {
  def greet() = "Hi"
}</span>

②在java中实现接口用implement,而在scala中,实现trait用extends。

<span style="font-size:14px;">class Dog extends Friendly {
  override def greet() = "Woof"
}</span>

此处,需要注意的一点是,与java不同,在scala中重写一个方法是需要指定override关键词的。如果重写一个方法时,没有加上override关键词,那么scala编译会无法通过。


java的interface和scala的trait的最大区别是,scala可以在一个class实例化的时候混合进一个trait。

<span style="font-size:14px;">trait Friendly {
  def greet() = "Hi"
}

class Dog extends Friendly {
  override def greet() = "Woof"
}

class HungryDog extends Dog {
  override def greet() = "I'd like to eat my own dog food"
}

trait ExclamatoryGreeter extends Friendly {
  override def greet() = super.greet() + "!"
}

var pet: Friendly = new Dog
println(pet.greet())

pet = new HungryDog
println(pet.greet())

pet = new Dog with ExclamatoryGreeter
println(pet.greet())

pet = new HungryDog with ExclamatoryGreeter   //可以混入多个的  :with a with b
println(pet.greet())</span>

这个特性类似于组合的,将公有的部分高度抽象统一,在需要的时候直接混入,就可以直接使用,很方便


(3)函数的的定义:(在scala中方法也是属性,所以方法是可以当作参数传递的(在Java中,方法是不能直接写个方法名在另外的方法中,而必须是function()//这个方法的返回参数作为当前方法的参数))

㈠带参数的
def function(str:String){}

㈡不带参数
def function ={} 或者 def function()={}

㈢匿名函数
()=>{//TODO} (lamada表达式)

用var定义一个函数:

<span style="font-size:14px;">  var increase = { (x: Int) =>
    x + 1;
    this.x = x;
  }</span>

调用方式:

<span style="font-size:14px;">  val zhu = w.increase;  w.increase;的返回值是一个函数
  // zhu.apply(10)  //完成匿名函数的调用</span>

将函数作为参数的函数(高阶函数):
<span style="font-size:14px;">def filesMatching(query: String,matcher: (String, String) => Boolean//定义的函数类型) = {
    for (file <- filesHere;if matcher(file.getName, query)) yield file
}</span>
<span style="font-size:14px;">调用方式:可以传入一个匿名参数
w.ff(10,{()=>print("zhuming") ;9})</span>

尾递归:尾递归是指一个递归的递归语句出现在最后一个地方,注意不能有其他的语句,如下不可以

<span style="font-size:14px;">def<span style="background-color: rgb(192, 192, 192);"> boom(x: Int)</span>: Int =
if (x == 0) throw new Exception("boom!")
<span style="background-color: rgb(192, 192, 192);">else boom(x-1)//  这样的好处是 在进行迭代计算的时候,不用开辟新栈,减少消耗有助于提高效率</span></span>

可变参数:注意scala只允许最后一个参数可变

<span style="font-size:14px;">def echo(args: String*) =for (arg <args) println(arg)</span>

事实上args是一个Array但是用这样的语法使得调用时,可以用多个参数调用但是不可以直接传递一个Array


闭包(函数作为一级概念的一个含义是,它们必须被识别为单独的结构,也称为闭包,闭包的概念就是为了将函数看作一个变量,而匿名函数可以简化闭包(闭包不要写成一个具体规范的函数而是直接写在方法的参数里的匿名函数·)

1.闭包会在每次外层函数调用的时候重新产生,就好像他们分别有两份一样,事实上可以在每次调用时把闭包函数所使用的变量绑定得到一个函数。

2.闭包语法:scala中不允许返回函数名,但是可以返回偏函数.

<span style="font-size:14px;">def makeIncreaser(more: Int) ={
        def other(x:Int)=x+more
        val addMore = other _
        addMore
    }</span>
<span style="font-size:14px;">或者返回匿名函数
def makeIncreaser(more: Int) ={ val addMore = (x:Int)=>{x+more}       addMore    }</span>



(4)属性的定义:

var 可变的属性 // var a =1 a=2 (可以)

val 不可变的实行 //val a=1 a=2 (报错)

主:var 和 val 可用来直接定义无参数的函数或者用来指代已经定义好的函数(有无参数都可以,不过一般用来书写类的set/get方法

var val def的使用:

子类中,def只能重写超类的def,val能重写超类的val或不带参数的def,var只能重写超类中抽象的var或者超类的getter/setter对


(5)柯里化:把原来需要接受两个参数的函数变成两个接受一个参数的函数,新的函数接受一个参数并返回一个接受一个参数的函数

(1)def mul(x:Inr,y:Int)={x*y}

(2)def mul(x:Int)=(y:Int)=>x*y

(3)(仅仅scala支持的简写)def mul(x:Int)(y:Int)={x*y}

调用方式:


(6)模式匹配(_
和 somethingElse 意思相同都是通用匹配)

<span style="font-size:14px;">def simplifyTop(expr: Expr): Expr = 
    expr match {
    case UnOp("",UnOp("",e)) => e // Double negation
    case BinOp("+", e, Number(0)) => e // Adding zero
    case BinOp("*", e, Number(1)) => e // Multiplying by one
    case _ => expr                //常量匹配
    case somethingElse => "not zero: " + somethingElse   //变量匹配
    在进行模式匹配的时候可以同样进行模式守卫
    case n: Int if 0 < n =>//TODO
}</span>

 (7)样例类:在类声明前面加上case关键字的叫做样例类

(8) 密封类:sealed abstract class Expr密封类仅允许同文件的类检测它,因此不用担心在模式匹配的时候出现未匹配的问题


数据结构:

(1)列表:

x::y::z      定义了一个三个元素的列表

x::y:::z 定义了一个两个元素的列表在于Z列表合并

(2)数组与泛型:在 Scala 中,数组表示为泛型化的 Array 类的实例,这正是
Scala 使用方括号(“[]”)而非尖括号(“<>”)来指明参数化类型的原因

(9)apply方法:apply方法出现在半生类独享object中,其作用类似在构造对象是不要使用new关键字,简化使用,在其内部其实通过new创建了这个对象并返回。


(10)预先定义(特质中有些字段没有出事话,如果要使用会出问题,所以要提前初始化):

	class a extends {初始化字段等} with 特质{xxxxxx}

(11)函数的懒执行(lazy):

柯里化

package scala2

class father {
<span style="color:#ff0000;">  def ma(s1:String)(s2:String) {</span>
    //import scala.math._
	print(s1)
	print(s2)
  }

<span style="color:#ff0000;">  val ma1=ma("zhu******") _;</span>
}

object father {
  def main(args: Array[String]) {
    val father = new father
    father.ma1("ming******");	
  }
  
} 

高阶函数:

package scala2

class father {
 <span style="color:#ff0000;"> def ma(s1:String)=(s2:String) => {</span>
    //import scala.math._
	print(s1)
	print(s2)
  }
  
<span style="color:#ff0000;">  val ma1=ma("zhu******");</span>
}

object father {
  def main(args: Array[String]) {
    val father = new father
    father.ma1("ming******");	
  }
  
} 
package _shiyong

class _test(opt:Int) {

  var s: Int=opt;
  def _shiy(fun: (Int) => Int) = fun(s)

}

object _test {
  def main(args: Array[String]) {
    var t = new _test(10)
    print(t._shiy(3 * _))
  }
}

抱歉!评论已关闭.