Skip to content

Instantly share code, notes, and snippets.

@morning21
Created August 5, 2017 12:30
Show Gist options
  • Save morning21/af965c2c5130684e10e1a702175e0151 to your computer and use it in GitHub Desktop.
Save morning21/af965c2c5130684e10e1a702175e0151 to your computer and use it in GitHub Desktop.

Scala

柯里化(Currying)

  • 把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。

例程

	object HelloWorld {
	   def main(args: Array[String]) {
	      println("Hello, world!")
	   }
	}

注意事项

  • 所有的类名首字母必须大写
  • 所有的方法名首字母必须小写
  • 程序文件名必须与对象名完全一致
  • Scala内部实现会使用转义的标识符,如:->使用$colon$minus%greater来表示
  • 定义包
	package com.runoob{
		class Helloworld
	}
  • import语句可以出现在任何地方
  • 如果想要引入包中的几个成员,可以用选取器件
	import java.awt.{Color, Font}
 
	// 重命名成员
	import java.util.{HashMap => JavaHashMap}
	 
	// 隐藏成员
	import java.util.{HashMap => _, _} // 引入了util包的所有成员,但是HashMap被隐藏了
  • 默认情况下,Scala会引入java.lang._、scala.和Predef.,这里能解释为什么以scala开头的包,在使用时都是省去scala的
  • 如果没有指明数据类型的情况下生命变量或者常量必须要给出其初始值,否则将报错
  • Scala支持多个变量的生命
	val xmax, ymax = 100  // xmax, ymax都声明为100
  • 如果方法返回值是元组,我们可以用val来声明一个元组
	scala> val pa = (40,"Foo")
	pa: (Int, String) = (40,Foo)

访问权限

  • Scala 中的 private 限定符,比 Java 更严格,在嵌套类情况下,外层类甚至不能访问被嵌套类的私有成员。
  • 在 scala 中,对保护(Protected)成员的访问比 java 更严格一些。因为它只允许保护成员在定义了该成员的的类的子类中被访问。而在java中,用protected关键字修饰的成员,除了定义了该成员的类的子类可以访问,同一个包里的其他类也可以进行访问

函数声明

  • 如果你不写等于号和方法主体,那么方法会被隐式声明为"抽象(abstract)",包含它的类型于是也是一个抽象类型。
	def functionName ([参数列表]) : [return type]
  • Scala 函数定义格式如下:
	def functionName ([参数列表]) : [return type] = {
	   function body
	   return [expr]
	}
  • 如果函数没有返回值,可以返回为 Unit,这个类似于 Java 的 void
  • 参数列表格式 a:Int, b:Int

闭包

  • 定义函数变量 multiplier 成为一个"闭包",因为它引用到函数外面定义的变量,定义这个函数的过程是将这个自由变量捕获而构成一个封闭的函数
	object Test {  
	def main(args: Array[String]) {  
	  println( "muliplier(1) value = " +  multiplier(1) )  
	  println( "muliplier(2) value = " +  multiplier(2) )  
	}  
	var factor = 3  
	val multiplier = (i:Int) => i * factor  
	} 

String

  • Scala没有String类型,实际上采用Java String。String 是一个不可变的对象,所以该对象不可被修改。这就意味着你如果修改字符串就会产生一个新的字符串对象。
    • 如果要可修改的字符串,可以使用String Builder类
	object Test {
	   def main(args: Array[String]) {
	      val buf = new StringBuilder;
	      buf += 'a'
	      buf ++= "bcdef"		// +=时,出现required char, found String
	      println( "buf is : " + buf.toString );
	   }
	}

for循环

	for( var x <- Range ){
	   statement(s);
	}
  • to/until
	object Test {
	   def main(args: Array[String]) {
	      var a = 0;
	      // for 循环
	      for( a <- 1 to 10){		//(1 - 10)
	      //for( a <- 1 until 10){	// (1 - 9)
	         println( "Value of a: " + a );
	      }
	   }
	}
  • ;
	object Test {
	   def main(args: Array[String]) {
	      var a = 0;
	      var b = 0;
	      // for 循环
	      for( a <- 1 to 3; b <- 1 to 3){		// 相当于双重循环,b为内层
	         println( "Value of a: " + a );
	         println( "Value of b: " + b );
	      }
	   }
	}
  • List
	object Test {
	   def main(args: Array[String]) {
	      var a = 0;
	      val numList = List(1,2,3,4,5,6);

	      // for 循环
	      for( a <- numList ){
	         println( "Value of a: " + a );
	      }
	   }
	}
  • 采用if循环过滤
	object Test {
	   def main(args: Array[String]) {
	      var a = 0;
	      val numList = List(1,2,3,4,5,6,7,8,9,10);

	      // for 循环
	      for( a <- numList
	           if a != 3; if a < 8 ){		// KEY
	         println( "Value of a: " + a );
	      }
	   }
	}
  • yield
	object Test {
	   def main(args: Array[String]) {
	      var a = 0;
	      val numList = List(1,2,3,4,5,6,7,8,9,10);

	      // for 循环
	      var retVal = for{ a <- numList 
	                        if a != 3; if a < 8
	                      }yield a

	      // 输出返回值
	      for( a <- retVal){
	         println( "Value of a: " + a );
	      }
	   }
	}

数组声明

	var z:Array[String] = new Array[String](3)
	var z = new Array[String](3)
	var z = Array("Runoob", "Baidu", "Google")
  • 多维数组
	import Array._

	object Test {
	   def main(args: Array[String]) {
	      var myMatrix = ofDim[Int](3,3)		// 二维数组
	      
	      // 创建矩阵
	      for (i <- 0 to 2) {
	         for ( j <- 0 to 2) {
	            myMatrix(i)(j) = j;
	         }
	      }
	      
	      // 打印二维阵列
	      for (i <- 0 to 2) {
	         for ( j <- 0 to 2) {
	            print(" " + myMatrix(i)(j));
	         }
	         println();
	      }
	    
	   }
	}
  • 合并数组 concat
	import Array._

	object Test {
	   def main(args: Array[String]) {
	      var myList1 = Array(1.9, 2.9, 3.4, 3.5)
	      var myList2 = Array(8.9, 7.9, 0.4, 1.5)

	      var myList3 =  concat( myList1, myList2)
	      
	      // 输出所有数组元素
	      for ( x <- myList3 ) {
	         println( x )
	      }
	   }
	}
  • 创建区间数组
	import Array._

	object Test {
	   def main(args: Array[String]) {
	      var myList1 = range(10, 20, 2)
	      var myList2 = range(10,20)

	      // 输出所有数组元素
	      for ( x <- myList1 ) {
	         print( " " + x ) // 10 12 14 16 18
	      }
	      println()
	      for ( x <- myList2 ) {
	         print( " " + x ) // 10 11 12 13 14 15 16 17 18 19
	      }
	   }
	}

Collection 集合 (未看完)

	// 定义整型 List
	val x = List(1,2,3,4)

	// 定义 Set
	var x = Set(1,3,5,7)

	// 定义 Map
	val x = Map("one" -> 1, "two" -> 2, "three" -> 3)

	// 创建两个不同类型元素的元组
	val x = (10, "Runoob")

	// 定义 Option
	val x:Option[Int] = Some(5)

Iterator 迭代器

  • Iterator不是一个集合,是一种用于访问集合的方法
  • 迭代器it的两个基本操作是next()和hasNext
  • it.max it.min it.size=it.length

继承和多态

  • 示例
	import java.io._

	class Point(xc: Int, yc: Int) {
	   var x: Int = xc
	   var y: Int = yc

	   def move(dx: Int, dy: Int) {
	      x = x + dx
	      y = y + dy
	      println ("x 的坐标点: " + x);
	      println ("y 的坐标点: " + y);
	   }
	}

	object Test {
	   def main(args: Array[String]) {
	      val pt = new Point(10, 20);

	      // 移到一个新的位置
	      pt.move(10, 10);
	   }
	}
  • 继承 (Scala 只允许继承一个父类)
    1. 重写一个非抽象方法必须使用override修饰符。
    2. 只有主构造函数才可以往基类的构造函数里写参数。
    3. 在子类中重写超类的抽象方法时,你不需要使用override关键字。
	class Point(xc: Int, yc: Int) {
	   var x: Int = xc
	   var y: Int = yc

	   def move(dx: Int, dy: Int) {
	      x = x + dx
	      y = y + dy
	      println ("x 的坐标点: " + x);
	      println ("y 的坐标点: " + y);
	   }
	}

	class Location(override val xc: Int, override val yc: Int,
	   val zc :Int) extends Point(xc, yc){
	   var z: Int = zc

	   def move(dx: Int, dy: Int, dz: Int) {
	      x = x + dx
	      y = y + dy
	      z = z + dz
	      println ("x 的坐标点 : " + x);
	      println ("y 的坐标点 : " + y);
	      println ("z 的坐标点 : " + z);
	   }
	}
  • 重写非抽象方法,需用override
class Person {
  var name = ""
  override def toString = getClass.getName + "[name=" + name + "]"	// 函数
}

class Employee extends Person {
  var salary = 0.0
  override def toString = super.toString + "[salary=" + salary + "]"
}

object Test extends App {
  val fred = new Employee
  fred.name = "Fred"
  fred.salary = 50000
  println(fred)
  //Employee[name=Fred][salary=50000.0]
}

单例对象 object (不懂)

  • 在 Scala 中,是没有 static 这个东西的,但是它也为我们提供了单例模式的实现方法,那就是使用关键字 object

  • Scala 中使用单例模式时,除了定义的类之外,还要定义一个同名的 object 对象,它和类的区别是,object对象不能带参数

  • 当单例对象与某个类共享同一个名称时,他被称作是这个类的伴生对象:companion object。你必须在同一个源文件里定义类和它的伴生对象。类被称为是这个单例对象的伴生类:companion class。类和它的伴生对象可以互相访问其私有成员

  • 单例对象

	import java.io._

	class Point(val xc: Int, val yc: Int) {
	   var x: Int = xc
	   var y: Int = yc
	   def move(dx: Int, dy: Int) {
	      x = x + dx
	      y = y + dy
	   }
	}

	object Test {
	   def main(args: Array[String]) {
	      val point = new Point(10, 20)
	      printPoint

	      def printPoint{
	         println ("x 的坐标点 : " + point.x);
	         println ("y 的坐标点 : " + point.y);
	      }
	   }
	}
  • 伴生对象示例
// 私有构造方法
class Marker private(val color:String) {

  println("创建" + this)
  
  override def toString(): String = "颜色标记:"+ color
  
}

// 伴生对象,与类共享名字,可以访问类的私有属性和方法
object Marker{
  
    private val markers: Map[String, Marker] = Map(
      "red" -> new Marker("red"),
      "blue" -> new Marker("blue"),
      "green" -> new Marker("green")
    )
    
    def apply(color:String) = {
      if(markers.contains(color)) markers(color) else null
    }
  
    
    def getMarker(color:String) = { 
      if(markers.contains(color)) markers(color) else null
    }
    def main(args: Array[String]) { 
        println(Marker("red"))  
        // 单例函数调用,省略了.(点)符号  
		println(Marker getMarker "blue")  
    }
}

Trait 特征

  • 相当于 Java 的接口,实际上它比接口还功能强大
  • 与接口不同的是,它还可以定义属性和方法的实现
  • 一般情况下Scala的类只能够继承单一父类,但是如果是 Trait(特征) 的话就可以继承多个,从结果来看就是实现了多重继承
  • 示例
	trait Equal {
	  def isEqual(x: Any): Boolean
	  def isNotEqual(x: Any): Boolean = !isEqual(x)
	}
  • 以上Trait(特征)由两个方法组成:isEqual 和 isNotEqual。isEqual 方法没有定义方法的实现,isNotEqual定义了方法的实现。子类继承特征可以实现未被实现的方法。所以其实 Scala Trait(特征)更像 Java 的抽象类
	trait Equal {
	  def isEqual(x: Any): Boolean
	  def isNotEqual(x: Any): Boolean = !isEqual(x)
	}

	class Point(xc: Int, yc: Int) extends Equal {
	  var x: Int = xc
	  var y: Int = yc
	  def isEqual(obj: Any) =
	    obj.isInstanceOf[Point] &&
	    obj.asInstanceOf[Point].x == x
	}

	object Test {
	   def main(args: Array[String]) {
	      val p1 = new Point(2, 3)
	      val p2 = new Point(2, 4)
	      val p3 = new Point(3, 3)

	      println(p1.isNotEqual(p2))
	      println(p1.isNotEqual(p3))
	      println(p1.isNotEqual(2))
	   }
	}

Scala 是Java的脚本化 面向函数:直奔主题 直接写程序,直接运行即可

Java javac java *.java ----> *.class ----> APP

Scala scalac scala *.scala ----> *.class ----> APP

val(value) 常量 var(variable) 变量,弱类型,scala支持类型推断

var x : String = "hello world" var x : Any = "hello world" (对应Java中的Object)

val x = 1.to(10) Range(1,2,···,10) val x = 1 to 10 Range(1,2,···,10)

scala 没有强制类型转换,只能通过函数转 val x = 97.toChar(); var a : Int = 100; var b : Short = 200; b = a; (错误) b = (Short)a; (错误) a = b.toInt(); b = a.toShort()

Scala 不支持++和--

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment