标签:apply 定义类 设置 实例成员 eva time 新建 字符 ext
scala> val myStr = "Hello World!"
myStr: String = Hello World!
scala> val myStr2 : String = "Hello World!"
myStr2: String = Hello World!
scala> val myStr3 : java.lang.String = "Hello World!"
myStr3: String = Hello World!
scala> var myPrice : Double = 9.9
myPrice: Double = 9.9
再次对myPrice进行赋值
scala> myPrice = 10.6
myPrice: Double = 10.6
Scala的数据类型包括:Byte、Char、Short、Int、Long、Float、Double和Boolean。和Java不同的是,在Scala中,这些类型都是“类”,并且都是包scala的成员,比如,Int的全名是scala.Int。对于字符串,Scala用java.lang.String类来表示字符串。
val i = 123 //123就是整数字面量 val i = 3.14 //3.14就是浮点数字面量 val i = true //true就是布尔型字面量 val i = ‘A‘ //‘A‘就是字符字面量 val i = "Hello" //"Hello"就是字符串字面量
a 方法 b
或a.方法(b)
示例:
scala> val sum1 = 5 + 3 //实际上调用了 (5).+(3) sum1: Int = 8 scala> val sum2 = (5).+(3) //可以发现,写成方法调用的形式,和上面得到相同的结果 sum2: Int = 8
和Java不同,在Scala中并没有提供++和–操作符
scala> var i = 5; i: Int = 5 scala> i += 1 //将i递增 scala> println(i) 6
在执行for循环时,我们经常会用到数值序列,比如,i的值从1循环到5,这时就可以采用Range来实现。
(1)创建一个从1到5的数值序列,包含区间终点5,步长为1
scala> 1 to 5 res0: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5)
// 或
scala> 1.to(5)
res0: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5)
(2)创建一个从1到10的数值序列,包含区间终点10,步长为2
scala> 1 to 10 by 2
res2: scala.collection.immutable.Range = Range(1, 3, 5, 7, 9)
(1)创建一个从1到5的数值序列,不包含区间终点5,步长为1
scala> 1 until 5
res1: scala.collection.immutable.Range = Range(1, 2, 3, 4)
(2)创建一个从1到5的数值序列,不包含区间终点5,步长为2
scala> 1 until 5 to 2
res1: scala.collection.immutable.Range = Range(1, 3)
print("My name is:")
print("Ziyu")
val i = 5; val j = 8; printf("My name is %s. I hava %d apples and %d eggs.\n","Ziyu",i,j)
scala> import java.io.PrintWriter import java.io.PrintWriter //这行是Scala解释器执行上面语句后返回的结果 scala> val out = new PrintWriter("output.txt") out: java.io.PrintWriter = java.io.PrintWriter@25641d39 //这行是Scala解释器执行上面语句后返回的结果 scala> for (i <- 1 to 5) out.println(i) scala> out.close()
scala> import scala.io.Source import scala.io.Source //这行是Scala解释器执行上面语句后返回的结果 scala> val inputFile = Source.fromFile("output.txt") inputFile: scala.io.BufferedSource = non-empty iterator //这行是Scala解释器执行上面语句后返回的结果 scala> val lines = inputFile.getLines //返回的结果是一个迭代器 lines: Iterator[String] = non-empty iterator //这行是Scala解释器执行上面语句后返回的结果 scala> for (line <- lines) println(line)
和Java一样,if语句可以采用各种嵌套的形式,比如:
val x = 3 if (x>0) { println("This is a positive number") } else if (x==0) { println("This is a zero") } else { println("This is a negative number") }
但是,有一点与Java不同的是,Scala中的if表达式的值可以赋值给变量,比如:
val x = 6 val a = if (x>0) 1 else -1
var i = 9 while (i > 0) { i -= 1 printf("i is %d\n",i) }
var i = 0 do { i += 1 println(i) }while (i<5)
for (i <- 1 to 5) println(i)
设置步长为2,如下所示:
for (i <- 1 to 5 by 2) println(i)
比如,我们只希望输出1到5之中的所有偶数,就需要使用到称为“守卫(guard)”的表达式,可以采用以下语句:
for (i <- 1 to 5 if i%2==0) println(i)
Scala也支持“多个生成器”的情形,可以用分号把它们隔开,比如:
for (i <- 1 to 5; j <- 1 to 3) println(i*j)
也可以给每个生成器都添加一个“守卫”,如下:
for (i <- 1 to 5 if i%2==0; j <- 1 to 3 if j!=i) println(i*j)
定长数组,就是长度不变的数组,在Scala中使用Array进行声明
val intValueArr = new Array[Int](3) //声明一个长度为3的整型数组,每个数组元素初始化为0 intValueArr(0) = 12 //给第1个数组元素赋值为12 intValueArr(1) = 45 //给第2个数组元素赋值为45 intValueArr(2) = 33 //给第3个数组元素赋值为33
实际上,Scala提供了更加简洁的数组声明和初始化方法,如下:
val intValueArr = Array(12,45,33)
val myStrArr = Array("BigData","Hadoop","Spark")
val intList = List(1,2,3)
由于列表的头部是一个元素,所以,我们可以使用::操作,在列表的头部增加新的元素,得到一个新的列表.
val intList = List(1,2,3)
val intListOther = 0::intList
也可以:
val intList = 1::2::3::Nil
Scala还为列表提供了一些常用的方法,比如,如果要实现求和,可以直接调用sum方法,如下:
intList.sum
元组是不同类型的值的聚集。元组和列表不同,列表中各个元素必须是相同类型,而元组可以包含不同类型的元素。
scala> val tuple = ("BigData",2015,45.0) tuple: (String, Int, Double) = (BigData,2015,45.0) //这行是Scala解释器返回的执行结果 scala> println(tuple._1) BigData scala> println(tuple._2) 2015 scala> println(tuple._3) 45.0
scala> var mySet = Set("Hadoop","Spark") mySet: scala.collection.immutable.Set[String] = Set(Hadoop, Spark) scala> mySet += "Scala" //向mySet中增加新的元素 scala> println(mySet.contains("Scala")) true
scala> import scala.collection.mutable.Set import scala.collection.mutable.Set scala> val myMutableSet = Set("Database","BigData") myMutableSet: scala.collection.mutable.Set[String] = Set(BigData, Database) scala> myMutableSet += "Cloud Computing" res0: myMutableSet.type = Set(BigData, Cloud Computing, Database) scala> println(myMutableSet) Set(BigData, Cloud Computing, Database)
val university = Map("XMU" -> "Xiamen University", "THU" -> "Tsinghua University","PKU"->"Peking University")
获取value
println(university("XMU"))
如果要检查映射中是否包含某个值,可以使用contains方法
val xmu = if (university.contains("XMU")) university("XMU") else 0 println(xmu)
import scala.collection.mutable.Map val university2 = Map("XMU" -> "Xiamen University", "THU" -> "Tsinghua University","PKU"->"Peking University") university2("XMU") = "Ximan University" //更新已有元素的值 university2("FZU") = "Fuzhou University" //添加新元素
也可以使用+=操作来添加新的元素,如下:
university2 + = ("TJU"->"Tianjin University") //添加一个新元素 university2 + = ("SDU"->"Shandong University","WHU"->"Wuhan University") //同时添加两个新元素
5.3 循环遍历
for ((k,v) <- 映射) 语句块
下面给出一个实例:
for ((k,v) <- university) printf("Code is : %s and name is: %s\n",k,v)
或者
val map = Map("zhangsan" -> 18, "li" -> 20, "wangwu" -> 23) for (i <- map) { println(i._1 + " ---- " + i._2) }
通常可以通过while循环或者for循环实现对迭代器的遍历。
while循环如下:
val iter = Iterator("Hadoop","Spark","Scala") while (iter.hasNext) { println(iter.next()) }
for循环如下:
val iter = Iterator("Hadoop","Spark","Scala") for (elem <- iter) { println(elem) }
最简单的类的定义形式是:
class Counter{ //这里定义类的字段和方法 }
然后,就可以使用new关键字来生成对象:
new Counter //或者new Counter()
下面我们给这个类增加字段和方法:
class Counter { private var value = 0 def increment(): Unit = { value += 1} def current(): Int = {value} }
下面我们新建对象,并调用其中的方法:
val myCounter = new Counter myCounter.increment() //或者也可以不用圆括号,写成myCounter.increment println(myCounter.current)
class Counter { var value = 0 //注意这里没有private修饰符,从而让这个变量对外部可见 def increment(step: Int): Unit = { value += step} def current(): Int = {value} } object MyCounter{ def main(args:Array[String]){ val myCounter = new Counter println(myCounter.value) //不是用getXxx获取字段的值 myCounter.value = 3 //不是用setXxx设置字段的值 myCounter.increment(1) //这里设置步长为1,每次增加1 println(myCounter.current) } }
在Scala中,可以通过定义类似getter和setter的方法,分别叫做value和value_=,具体如下:
class Counter { private var privateValue = 0 //变成私有字段,并且修改字段名称 def value = privateValue //定义一个方法,方法的名称就是原来我们想要的字段的名称 def value_=(newValue: Int){ if (newValue > 0) privateValue = newValue //只有提供的新值是正数,才允许修改 } def increment(step: Int): Unit = { value += step} def current(): Int = {value} } object MyCounter{ def main(args:Array[String]){ val myCounter = new Counter println(myCounter.value) //打印value的初始值 myCounter.value = 3 //为value设置新的值 println(myCounter.value) //打印value的新值 myCounter.increment(1) //这里设置步长为1,每次增加1 println(myCounter.current) } }
class Counter { private var value = 0 //value用来存储计数器的起始值 private var name = "" //表示计数器的名称 private var mode = 1 //mode用来表示计数器类型(比如,1表示步数计数器,2表示时间计数器) def this(name: String){ //第一个辅助构造器 this() //调用主构造器 this.name = name } def this (name: String, mode: Int){ //第二个辅助构造器 this(name) //调用前一个辅助构造器 this.mode = mode } def increment(step: Int): Unit = { value += step} def current(): Int = {value} def info(): Unit = {printf("Name:%s and mode is %d\n",name,mode)} } object MyCounter{ def main(args:Array[String]){ val myCounter1 = new Counter //主构造器 val myCounter2 = new Counter("Runner") //第一个辅助构造器,计数器的名称设置为Runner,用来计算跑步步数 val myCounter3 = new Counter("Timer",2) //第二个辅助构造器,计数器的名称设置为Timer,用来计算秒数 myCounter1.info //显示计数器信息 myCounter1.increment(1) //设置步长 printf("Current Value is: %d\n",myCounter1.current) //显示计数器当前值 myCounter2.info //显示计数器信息 myCounter2.increment(2) //设置步长 printf("Current Value is: %d\n",myCounter2.current) //显示计数器当前值 myCounter3.info //显示计数器信息 myCounter3.increment(3) //设置步长 printf("Current Value is: %d\n",myCounter3.current) //显示计数器当前值 } } 编译执行上述代码后,得到如下结果: Name: and mode is 1 Current Value is: 1 Name:Runner and mode is 1 Current Value is: 2 Name:Timer and mode is 2 Current Value is: 3 主构造器 Scala的每个类都有主构造器。但是,Scala的主构造器和Java有着明显的不同,Scala的主构造器是整个类体,需要在类名称后面罗列出构造器所需的所有参数,这些参数被编译成字段,字段的值就是创建对象时传入的参数的值。 对于上面给计数器设置name和mode的例子,刚才我们是使用辅助构造器来对name和mode的值进行设置,现在我们重新来一次,这次我们转而采用主构造器来设置name和mode的值。 class Counter(val name: String, val mode: Int) { private var value = 0 //value用来存储计数器的起始值 def increment(step: Int): Unit = { value += step} def current(): Int = {value} def info(): Unit = {printf("Name:%s and mode is %d\n",name,mode)} } object MyCounter{ def main(args:Array[String]){ val myCounter = new Counter("Timer",2) myCounter.info //显示计数器信息 myCounter.increment(1) //设置步长 printf("Current Value is: %d\n",myCounter.current) //显示计数器当前值 } }
下面是单例对象的定义:
object Person { private var lastId = 0 //一个人的身份编号 def newPersonId() = { lastId +=1 lastId } }
在Java中,我们经常需要用到同时包含实例方法和静态方法的类,在Scala中可以通过伴生对象来实现。当单例对象与某个类具有相同的名称时,它被称为这个类的“伴生对象”。类和它的伴生对象必须存在于同一个文件中,而且可以相互访问私有成员(字段和方法)。
class Person { private val id = Person.newPersonId() //调用了伴生对象中的方法 private var name = "" def this(name: String) { this() this.name = name } def info() { printf("The id of %s is %d.\n",name,id)} } object Person { private var lastId = 0 //一个人的身份编号 private def newPersonId() = { lastId +=1 lastId } def main(args: Array[String]){ val person1 = new Person("Ziyu") val person2 = new Person("Minxing") person1.info() person2.info() } }
伴生对象中定义的newPersonId()实际上就实现了Java中静态(static)方法的功能
实际上,在编译上面的源代码文件以后,在Scala里面的class和object在Java层面都会被合二为一,class里面的成员成了实例成员,object成员成了static成员。并且伴生对象Person的定义的方法不能用private修饰符,必须去掉,因为如果不去掉,作为伴生对象的私有方法,在javap反编译后,在执行结果中是看不到这个方法的。
object apply 是一种比较普遍用法。 主要用来解决复杂对象的初始化问题,同时也是单例.
class TestApplyClass { def apply(param: String): String = { println("apply method called, parameter is: " + param) "Hello World!" } } val myObject = new TestApplyClass println(myObject("param1"))
运行后会得到以下结果:
apply method is called, parameter is:param1
Hello World!
下面我们测试一个伴生类和伴生对象中的apply方法实例。请在Linux系统的“/usr/local/scala/mycode/test.scala”文件中输入以下代码:
class TestApplyClassAndObject { } class ApplyTest{ def apply() = println("apply method in class is called!") def greetingOfClass: Unit ={ println("Greeting method in class is called.") } } object ApplyTest{ def apply() = { println("apply method in object is called") new ApplyTest() } } object TestApplyClassAndObject{ def main (args: Array[String]) { val a = ApplyTest() //这里会调用伴生对象中的apply方法 a.greetingOfClass a() // 这里会调用伴生类中的apply方法 } }
上述代码执行后得到以下结果:
apply method in object is called Greeting method in class is called. apply method in class is called!
我们通常将伴生对象作为工厂使用,这样就不需要使用关键字new来创建一个实例化对象了,具体实例如下:
class Car(name: String){ def info() {println("Car name is "+ name)} } object Car { def apply(name: String) = new Car(name) //apply方法会调用伴生类Car的构造方法创建一个Car类的实例化对象 } object MyTest{ def main (args: Array[String]) { val mycar = Car("BMW") //这里会调用伴生对象中的apply方法,apply方法会创建一个Car类的实例化对象 mycar.info() } }
上述代码执行后得到以下结果:
Car name is BMW
///
标签:apply 定义类 设置 实例成员 eva time 新建 字符 ext
原文地址:https://www.cnblogs.com/erlou96/p/14365589.html