modify
This commit is contained in:
parent
d09ca11daa
commit
52a294dbe6
@ -170,7 +170,7 @@ TODO
|
||||
7. [常用集合类型之——Map & Tuple](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Scala映射和元组.md)
|
||||
8. [类和对象](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Scala类和对象.md)
|
||||
9. [继承和特质](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Scala继承和特质.md)
|
||||
10. [函数和闭包](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Scala函数和闭包.md)
|
||||
10. [函数 & 闭包 & 柯里化](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Scala函数和闭包.md)
|
||||
11. [模式匹配](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Scala模式匹配.md)
|
||||
12. [类型参数](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Scala类型参数.md)
|
||||
13. [隐式转换和隐式参数](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Scala隐式转换和隐式参数.md)
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
### 1.1 函数与方法
|
||||
|
||||
在Scala中,函数与方法的区别非常小,如果函数作为某个对象的成员,这样的函数被称为方法,否则就是一个正常的函数。
|
||||
Scala中函数与方法的区别非常小,如果函数作为某个对象的成员,这样的函数被称为方法,否则就是一个正常的函数。
|
||||
|
||||
```scala
|
||||
// 定义方法
|
||||
@ -32,7 +32,7 @@ println(multi1(3)) //输出 9
|
||||
println(multi2(3)) //输出 9
|
||||
```
|
||||
|
||||
其实对于定义函数,使用val和def并没有区别,你也可以使用`def`定义函数:
|
||||
也可以使用`def`定义函数:
|
||||
|
||||
```scala
|
||||
def multi3 = (x: Int) => {x * x}
|
||||
@ -52,14 +52,14 @@ multi2: Int => Int = $$Lambda$1092/594363215@1dd1a777
|
||||
scala> def multi3 = (x: Int) => {x * x}
|
||||
multi3: Int => Int
|
||||
|
||||
// 如果有多个参数,则类型(参数类型,参数类型 ...)=>返回值类型
|
||||
// 如果有多个参数,则类型为:(参数类型,参数类型 ...)=>返回值类型
|
||||
scala> val multi4 = (x: Int,name: String) => {name + x * x }
|
||||
multi4: (Int, String) => String = $$Lambda$1093/1039732747@2eb4fe7
|
||||
```
|
||||
|
||||
### 1.3 一等公民&匿名函数
|
||||
|
||||
在Scala中函数是一等公民,这意味着不仅可以定义函数并调用它们,还可以用匿名的字面量来编写函数并将它们作为值进行传递:
|
||||
在Scala中函数是一等公民,这意味着不仅可以定义函数并调用它们,还可以将它们作为值进行传递:
|
||||
|
||||
```scala
|
||||
import scala.math.ceil
|
||||
@ -93,7 +93,7 @@ object ScalaApp extends App {
|
||||
|
||||
#### 1. 可变长度参数列表
|
||||
|
||||
在Java中如果你想要传递可变长度的参数列表,则需要使用`String ...args`这种语法,Scala中等效的语法为`args: String*`。
|
||||
在Java中如果你想要传递可变长度的参数,需要使用`String ...args`这种形式,Scala中等效的表达为`args: String*`。
|
||||
|
||||
```scala
|
||||
object ScalaApp extends App {
|
||||
@ -110,7 +110,7 @@ flink
|
||||
|
||||
#### 2. 传递具名参数
|
||||
|
||||
向函数传递参数时候可以指定具体的名称。
|
||||
向函数传递参数时候可以指定具体的参数名。
|
||||
|
||||
```scala
|
||||
object ScalaApp extends App {
|
||||
@ -127,7 +127,7 @@ object ScalaApp extends App {
|
||||
|
||||
#### 3. 默认值参数
|
||||
|
||||
可以为函数的参数指定默认值。
|
||||
在定义函数时,可以为参数指定默认值。
|
||||
|
||||
```scala
|
||||
object ScalaApp extends App {
|
||||
@ -163,7 +163,7 @@ val addMore = (x: Int) => x + more
|
||||
这里需要注意的是,闭包捕获的是变量本身,即是对变量本身的引用,这意味着:
|
||||
|
||||
+ 闭包外部对自由变量的修改,在闭包内部是可见的;
|
||||
+ 闭包内部对自由变量的修改,在闭包外部也是可见的;
|
||||
+ 闭包内部对自由变量的修改,在闭包外部也是可见的。
|
||||
|
||||
```scala
|
||||
// 声明more变量
|
||||
@ -239,7 +239,7 @@ object ScalaApp extends App {
|
||||
x * x
|
||||
}
|
||||
|
||||
// 2.定义高阶函数: 第一个参数是类型为Int => Int的函数,第二个参数为Int类型的值
|
||||
// 2.定义高阶函数: 第一个参数是类型为Int => Int的函数
|
||||
def multi(fun: Int => Int, x: Int) = {
|
||||
fun(x) * 100
|
||||
}
|
||||
@ -267,8 +267,8 @@ object ScalaApp extends App {
|
||||
|
||||
这里当你调用curriedSum时候,实际上是连着做了两次传统的函数调用,实际执行的柯里化过程如下:
|
||||
|
||||
+ 第一次调用接收一个名为x的int参数,返回一个用于第二次调用的函数,假设x为2,则返回函数`2+y`;
|
||||
+ 返回的函数接收Int参数y,并计算并返回值`2+3`的值。
|
||||
+ 第一次调用接收一个名为`x`的Int型参数,返回一个用于第二次调用的函数,假设`x`为2,则返回函数`2+y`;
|
||||
+ 返回的函数接收参数`y`,并计算并返回值`2+3`的值。
|
||||
|
||||
想要获得柯里化的中间返回的函数其实也比较简单:
|
||||
|
||||
|
@ -32,8 +32,8 @@ scala> list(1) = "hive"
|
||||
|
||||
Scala中List具有以下两个特性:
|
||||
|
||||
+ 同构(homogeneous):同一个List中的所有元素都必须是相同的类型;
|
||||
+ 协变(covariant):如果S是T的子类型,那么`List[S]`就是`List[T]`的子类型,例如`List[String]`是`List[Object]`的子类型。
|
||||
+ **同构(homogeneous)**:同一个List中的所有元素都必须是相同的类型;
|
||||
+ **协变(covariant)**:如果S是T的子类型,那么`List[S]`就是`List[T]`的子类型,例如`List[String]`是`List[Object]`的子类型。
|
||||
|
||||
需要特别说明的是空列表的类型为`List[Nothing]`:
|
||||
|
||||
@ -127,9 +127,9 @@ res2: scala.collection.immutable.Range = Range(0, 1, 2)
|
||||
|
||||
### 5.3 take & drop & splitAt
|
||||
|
||||
- take:获取前n个元素;
|
||||
- drop:删除前n个元素;
|
||||
- splitAt:从第几个位置开始拆分。
|
||||
- **take**:获取前n个元素;
|
||||
- **drop**:删除前n个元素;
|
||||
- **splitAt**:从第几个位置开始拆分。
|
||||
|
||||
```scala
|
||||
scala> list take 2
|
||||
@ -168,14 +168,14 @@ res7: (List[String], List[Int]) = (List(hadoop, spark, storm),List(10, 20, 30))
|
||||
|
||||
### 5.6 toString & mkString
|
||||
|
||||
toString 返回 list的字符串表现形式。
|
||||
toString 返回List的字符串表现形式。
|
||||
|
||||
```scala
|
||||
scala> list.toString
|
||||
res8: String = List(hadoop, spark, storm)
|
||||
```
|
||||
|
||||
如果想改变list的字符串表现形式,可以使用mkString,mkString有三个重载方法:
|
||||
如果想改变List的字符串表现形式,可以使用mkString。mkString有三个重载方法,方法定义如下:
|
||||
|
||||
```scala
|
||||
// start:前缀 sep:分隔符 end:后缀
|
||||
@ -335,7 +335,7 @@ res27: (List[Int], List[Int]) = (List(1, 2, 3),List(-4, 5))
|
||||
|
||||
### 6.3 列表检查:forall & exists
|
||||
|
||||
forall检查List中所有元素,如果所有元素都满足条件,则返回true;
|
||||
forall检查List中所有元素,如果所有元素都满足条件,则返回true。
|
||||
|
||||
```scala
|
||||
scala> List(1, 2, 3, -4, 5) forall ( _ > 0 )
|
||||
|
@ -98,18 +98,18 @@ object ScalaApp extends App {
|
||||
|
||||
### 1.4 提取器
|
||||
|
||||
数组、列表和元组能使用模式匹配,都是依靠提取器(extractor)机制,它们伴生对象中定义unapply或unapplySeq方法:
|
||||
数组、列表和元组能使用模式匹配,都是依靠提取器(extractor)机制,它们伴生对象中定义了`unapply`或`unapplySeq`方法:
|
||||
|
||||
+ unapply方法用于提取固定数量的对象;
|
||||
+ unapplySeq用于提取一个序列;
|
||||
+ **unapply**:用于提取固定数量的对象;
|
||||
+ **unapplySeq**:用于提取一个序列;
|
||||
|
||||
以下是`Array.scala`类源码中定义的`unapplySeq`方法:
|
||||
这里以数组为例,`Array.scala`定义了`unapplySeq`方法:
|
||||
|
||||
```scala
|
||||
def unapplySeq[T](x : scala.Array[T]) : scala.Option[scala.IndexedSeq[T]] = { /* compiled code */ }
|
||||
```
|
||||
|
||||
`unapplySeq`返回一个序列值,即数组中的值,以和模式匹配case语句中的表达式进行对应位置的值匹配。
|
||||
`unapplySeq`返回一个序列,包含数组中的所有值,这样在模式匹配时,才能知道对应位置上的值。
|
||||
|
||||
|
||||
|
||||
@ -138,7 +138,7 @@ case class Student(name: String, age: Int) extends Person {}
|
||||
|
||||
- 构造器中每个参数都默认为`val`;
|
||||
- 自动地生成`equals, hashCode, toString, copy`等方法;
|
||||
- 伴生对象中自动生成`apply`方法,使得不用new关键字就能构造出相应的对象;
|
||||
- 伴生对象中自动生成`apply`方法,使得可以不用new关键字就能构造出相应的对象;
|
||||
- 伴生对象中自动生成`unapply`方法,以支持模式匹配。
|
||||
|
||||
除了上面的特征外,样例类和其他类相同,可以任意添加方法和字段,扩展它们。
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
## 一、初识类和对象
|
||||
|
||||
Scala中的类与Java中的类具有非常多的相似性,这里为了有个直观上的印象,首先给出一个类的示例。
|
||||
Scala的类与Java的类具有非常多的相似性,示例如下:
|
||||
|
||||
```scala
|
||||
// 1. 在scala中,类不需要用public声明,所有的类都具有公共的可见性
|
||||
@ -26,11 +26,11 @@ class Person {
|
||||
// 2. 声明私有变量,用var修饰的变量默认拥有getter/setter属性
|
||||
private var age = 0
|
||||
|
||||
// 3.如果声明的变量不需要进行初始赋值,此时scala无法进行类型推荐,需要显式指明类型
|
||||
// 3.如果声明的变量不需要进行初始赋值,此时Scala就无法进行类型推断,所以需要显式指明类型
|
||||
private var name: String = _
|
||||
|
||||
|
||||
// 4. 定义方法,应该指明传参类型和返回值的类型
|
||||
// 4. 定义方法,应指明传参类型。返回值类型不是必须的,Scala可以自动推断出来,但是为了方便调用者,建议指明
|
||||
def growUp(step: Int): Unit = {
|
||||
age += step
|
||||
}
|
||||
@ -58,7 +58,7 @@ class Person {
|
||||
object Person {
|
||||
|
||||
def main(args: Array[String]): Unit = {
|
||||
// 8.创建类的实例对象
|
||||
// 8.创建类的实例
|
||||
val counter = new Person()
|
||||
// 9.用var修饰的变量默认拥有getter/setter属性,可以直接对其进行赋值
|
||||
counter.age = 12
|
||||
@ -132,7 +132,7 @@ object Person {
|
||||
> > javap -private Person
|
||||
> ```
|
||||
>
|
||||
> 编译结果如下,从编译结果可以看到实际的get和set的方法名,同时也验证了成员变量默认的可见性为public。
|
||||
> 编译结果如下,从编译结果可以看到实际的get和set的方法名(因为JVM不允许在方法名中出现=,所以它被翻译成$eq),同时也验证了成员变量默认的可见性为public。
|
||||
>
|
||||
> ```java
|
||||
> Compiled from "Person.scala"
|
||||
@ -172,7 +172,7 @@ object Person {
|
||||
|
||||
### 2.4 主构造器
|
||||
|
||||
和Java不同的是,Scala类的主构造器直接写在类名后面,同时需要注意以下两点:
|
||||
和Java不同的是,Scala类的主构造器直接写在类名后面,但注意以下两点:
|
||||
|
||||
+ 主构造器传入的参数默认就是val类型的,即不可变,你没有办法在内部改变传参;
|
||||
+ 写在主构造器中的代码块会在类初始化的时候被执行,功能类似于Java的静态代码块`static{}`
|
||||
@ -206,7 +206,7 @@ heibaiying:20
|
||||
|
||||
辅助构造器有两点硬性要求:
|
||||
|
||||
+ 辅助构造器的名称必须为this;
|
||||
+ 辅助构造器的名称必须为this;
|
||||
+ 每个辅助构造器必须以主构造器或其他的辅助构造器的调用开始。
|
||||
|
||||
```scala
|
||||
@ -236,7 +236,7 @@ object Person {
|
||||
|
||||
### 2.6 方法传参不可变
|
||||
|
||||
在Scala中,方法传参默认是val类型,即不可变,这意味着你在方法体内部不能改变传入的参数。这和scala的设计理念有关,Scala遵循函数式编程理念,强调方法不应该有副作用。
|
||||
在Scala中,方法传参默认是val类型,即不可变,这意味着你在方法体内部不能改变传入的参数。这和Scala的设计理念有关,Scala遵循函数式编程理念,强调方法不应该有副作用。
|
||||
|
||||
```scala
|
||||
class Person() {
|
||||
@ -378,16 +378,19 @@ object Color extends Enumeration {
|
||||
使用枚举类:
|
||||
|
||||
```scala
|
||||
// 1.使用类型别名导入枚举类
|
||||
import com.heibaiying.Color.Color
|
||||
|
||||
object ScalaApp extends App {
|
||||
|
||||
// 1.使用枚举类型,这种情况下需要导入枚举类,在枚举类中定义的类型别名就有用了
|
||||
// 2.使用枚举类型,这种情况下需要导入枚举类
|
||||
def printColor(color: Color): Unit = {
|
||||
println(color.toString)
|
||||
}
|
||||
|
||||
// 2.判断传入值和枚举值是否相等
|
||||
// 3.判断传入值和枚举值是否相等
|
||||
println(Color.YELLOW.toString == "yellow")
|
||||
// 3.遍历枚举类和值
|
||||
// 4.遍历枚举类和值
|
||||
for (c <- Color.values) println(c.id + ":" + c.toString)
|
||||
}
|
||||
|
||||
|
@ -60,9 +60,7 @@ object Utils {
|
||||
|
||||
### 2.1 类型上界限定
|
||||
|
||||
Scala和Java一样,对于对象之间进行大小比较,要求被比较的对象实现`java.lang.Comparable`接口。
|
||||
|
||||
所以如果想对泛型进行比较,需要限定类型上界为`java.lang.Comparable`,语法为` S <: T`,代表类型S是类型T的子类或其本身。示例如下:
|
||||
Scala和Java一样,对于对象之间进行大小比较,要求被比较的对象实现`java.lang.Comparable`接口。所以如果想对泛型进行比较,需要限定类型上界为`java.lang.Comparable`,语法为` S <: T`,代表类型S是类型T的子类或其本身。示例如下:
|
||||
|
||||
```scala
|
||||
// 使用 <: 符号,限定T必须是Comparable[T]的子类型
|
||||
@ -126,7 +124,7 @@ trait Ordered[A] extends Any with java.lang.Comparable[A] {
|
||||
|
||||
<div align="center"> <img src="https://github.com/heibaiying/BigData-Notes/blob/master/pictures/scala-richInt.png"/> </div>
|
||||
|
||||
要想解决传入数值无法进行比较的问题,可以使用视图界定。语法为`T <% U`,代表T能够通过隐式转换转为U,即允许Int型参数在无法进行比较的时候转换为RichInt类型。示例如下:
|
||||
要想解决传入数值无法进行比较的问题,可以使用视图界定。语法为`T <% U`,代表T能够通过隐式转换转为U,即允许Int型参数在无法进行比较的时候转换为RichInt类型。示例如下:
|
||||
|
||||
```scala
|
||||
// 视图界定符号 <%
|
||||
@ -147,7 +145,7 @@ class Pair[T <% Comparable[T]](val first: T, val second: T) {
|
||||
|
||||
### 2.3 类型约束
|
||||
|
||||
如果你用的Scala是2.11+,会发现IDEA会提示视图界定已被标识为废弃。官方推荐使用类型约束(type constraint)来实现同样的功能,其本质是使用隐式参数进行隐式转换,示例如下:
|
||||
如果你用的Scala是2.11+,会发现视图界定已被标识为废弃。官方推荐使用类型约束(type constraint)来实现同样的功能,其本质是使用隐式参数进行隐式转换,示例如下:
|
||||
|
||||
```scala
|
||||
// 1.使用隐式参数隐式转换为Comparable[T]
|
||||
@ -224,7 +222,7 @@ object ScalaApp extends App {
|
||||
}
|
||||
```
|
||||
|
||||
Scala针对这个问题,提供了ClassTag上下文界定,即把泛型的信息存储在ClassTag中,这样在运行阶段需要时,只需要从中进行获取即可。其语法为`T : ClassTag`,示例如下:
|
||||
Scala针对这个问题,提供了ClassTag上下文界定,即把泛型的信息存储在ClassTag中,这样在运行阶段需要时,只需要从ClassTag中进行获取即可。其语法为`T : ClassTag`,示例如下:
|
||||
|
||||
```scala
|
||||
import scala.reflect._
|
||||
@ -309,7 +307,7 @@ object ScalaApp extends App {
|
||||
|
||||
### 3.1 Comparable
|
||||
|
||||
```scala
|
||||
```java
|
||||
import java.util.Arrays;
|
||||
// 实现Comparable接口
|
||||
public class Person implements Comparable<Person> {
|
||||
@ -342,7 +340,7 @@ ying:77
|
||||
|
||||
### 3.2 Comparator
|
||||
|
||||
```scala
|
||||
```java
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
|
||||
|
@ -32,7 +32,7 @@ Scala中继承关系如下图:
|
||||
|
||||
### 1.2 extends & override
|
||||
|
||||
Scala的集成机制和Java有很多相似之处,比如都使用`extends`关键字表示继承,都使用`override`关键字表示重写父类的方法或成员变量。下面给出一个Scala继承的示例:
|
||||
Scala的集成机制和Java有很多相似之处,比如都使用`extends`关键字表示继承,都使用`override`关键字表示重写父类的方法或成员变量。示例如下:
|
||||
|
||||
```scala
|
||||
//父类
|
||||
@ -102,7 +102,7 @@ class Employee(name:String,age:Int,salary:Double) extends Person(name:String,age
|
||||
|
||||
### 1.4 类型检查和转换
|
||||
|
||||
想要实现类检查可以使用`isInstanceOf`,判断一个实例是否来源于某个类或者其子类,如果是,则可以使用`asInstanceOf`进行强制类型转换。
|
||||
想要实现类检查可以使用`isInstanceOf`,判断一个实例是否来源于某个类或者其子类,如果是,则可以使用`asInstanceOf`进行强制类型转换。
|
||||
|
||||
```scala
|
||||
object ScalaApp extends App {
|
||||
@ -208,7 +208,7 @@ class Employee extends {
|
||||
|
||||
但是这种语法也有其限制:你只能在上面代码块中重写已有的变量,而不能定义新的变量和方法,定义新的变量和方法只能写在下面代码块中。
|
||||
|
||||
>**注意事项**:不仅是类的继承存在这个问题,后文介绍的特质(trait)的继承也存在这个问题,也同样可以通过提前定义来解决。即便可以通过多种方法解决该问题,但还是建议合理设计继承以规避此类问题。
|
||||
>**注意事项**:类的继承和下文特质(trait)的继承都存在这个问题,也同样可以通过提前定义来解决。虽然如此,但还是建议合理设计以规避该类问题。
|
||||
|
||||
<br/>
|
||||
|
||||
@ -270,7 +270,7 @@ trait Logger {
|
||||
}
|
||||
```
|
||||
|
||||
想要使用特质,需要使用`extends`关键字,而不是`implements`关键字,如果想要添加多个特质,可以使用`with`关键字。
|
||||
想要使用特质,需要使用`extends`关键字,而不是`implements`关键字,如果想要添加多个特质,可以使用`with`关键字。
|
||||
|
||||
```scala
|
||||
// 1.使用extends关键字,而不是implements,如果想要添加多个特质,可以使用with关键字
|
||||
@ -310,7 +310,7 @@ class InfoLogger extends Logger {
|
||||
|
||||
### 3.3 带有特质的对象
|
||||
|
||||
Scala支持在类定义的时混入`父类trait`,而在类实例化为具体对象的时候指明其实际使用的`子类trait`。下面给出一个示例:
|
||||
Scala支持在类定义的时混入`父类trait`,而在类实例化为具体对象的时候指明其实际使用的`子类trait`。示例如下:
|
||||
|
||||
<div align="center"> <img src="https://github.com/heibaiying/BigData-Notes/blob/master/pictures/scala带有特质的对象.png"/> </div>
|
||||
|
||||
@ -388,9 +388,9 @@ object ScalaApp extends App {
|
||||
class Employee extends Person with InfoLogger with ErrorLogger {...}
|
||||
```
|
||||
|
||||
1. 超类首先被构造(Person构造器执行);
|
||||
1. 超类首先被构造,即Person的构造器首先被执行;
|
||||
2. 特质的构造器在超类构造器之前,在类构造器之后;特质由左到右被构造;每个特质中,父特质首先被构造;
|
||||
+ Logger构造器执行(Logger是InfoLogger的父类);
|
||||
+ Logger构造器执行(Logger是InfoLogger的父类);
|
||||
+ InfoLogger构造器执行;
|
||||
+ ErrorLogger构造器执行;
|
||||
3. 所有超类和特质构造完毕,子类才会被构造。
|
||||
|
@ -129,7 +129,7 @@ This is Class B
|
||||
|
||||
上面我们使用的方法相当于直接定义在执行代码的作用域中,下面分别给出其他两种定义的代码示例:
|
||||
|
||||
定义在原类型的伴生对象中:
|
||||
**定义在原类型的伴生对象中**:
|
||||
|
||||
```scala
|
||||
class Person(val name: String)
|
||||
@ -154,7 +154,7 @@ object ScalaApp extends App {
|
||||
}
|
||||
```
|
||||
|
||||
定义在一个公共的对象中:
|
||||
**定义在一个公共的对象中**:
|
||||
|
||||
```scala
|
||||
object Convert {
|
||||
@ -167,12 +167,11 @@ object Convert {
|
||||
import com.heibaiying.Convert._
|
||||
|
||||
object ScalaApp extends App {
|
||||
// 这样普通人也能举起雷神之锤
|
||||
new Person("普通人").hammer()
|
||||
}
|
||||
```
|
||||
|
||||
> 注:Scala中隐式转换函数大部分定义在`Predef.scala`中,你可以打开源文件查看,也可以在Scala交互式命令行中采用`:implicit -v`查看全部隐式转换函数。
|
||||
> 注:Scala自身的隐式转换函数大部分定义在`Predef.scala`中,你可以打开源文件查看,也可以在Scala交互式命令行中采用`:implicit -v`查看全部隐式转换函数。
|
||||
|
||||
<br/>
|
||||
|
||||
@ -180,7 +179,7 @@ object ScalaApp extends App {
|
||||
|
||||
### 2.1 使用隐式参数
|
||||
|
||||
函数或方法可以带有一个标记为`implicit`的参数列表,这种情况下,编译器将会查找默认值,提供给函数调用。
|
||||
在定义函数或方法时可以使用标记为`implicit`的参数,这种情况下,编译器将会查找默认值,提供给函数调用。
|
||||
|
||||
```scala
|
||||
// 定义分隔符类
|
||||
@ -243,7 +242,7 @@ formatted("this is context")
|
||||
|
||||
我们上面示例程序相当于直接定义执行代码的上下文作用域中,下面给出其他两种方式的示例:
|
||||
|
||||
定义在隐式参数对应类的伴生对象中;
|
||||
**定义在隐式参数对应类的伴生对象中**;
|
||||
|
||||
```scala
|
||||
class Delimiters(val left: String, val right: String)
|
||||
@ -264,7 +263,7 @@ object ScalaApp extends App {
|
||||
}
|
||||
```
|
||||
|
||||
统一定义在一个文件中,在使用时候导入:
|
||||
**统一定义在一个文件中,在使用时候导入**:
|
||||
|
||||
```scala
|
||||
object Convert {
|
||||
@ -292,9 +291,7 @@ object ScalaApp extends App {
|
||||
def smaller[T] (a: T, b: T) = if (a < b) a else b
|
||||
```
|
||||
|
||||
在Scala中如果定义了一个如上所示的比较对象大小的泛型方法,你会发现无法通过编译。对于对象之间进行大小比较,Scala和Java一样,都要求被比较的对象需要实现java.lang.Comparable接口。
|
||||
|
||||
在Scala中,直接继承Java中Comparable接口的是特质Ordered,它在继承compareTo方法的基础上,额外定义了关系符方法,源码如下:
|
||||
在Scala中如果定义了一个如上所示的比较对象大小的泛型方法,你会发现无法通过编译。对于对象之间进行大小比较,Scala和Java一样,都要求被比较的对象需要实现java.lang.Comparable接口。在Scala中,直接继承Java中Comparable接口的是特质Ordered,它在继承compareTo方法的基础上,额外定义了关系符方法,源码如下:
|
||||
|
||||
```scala
|
||||
trait Ordered[A] extends Any with java.lang.Comparable[A] {
|
||||
@ -336,7 +333,7 @@ object Pair extends App {
|
||||
|
||||
#### 2. 利用隐式参数进行隐式转换
|
||||
|
||||
在Scala2.11+后,视图界定被标识为废弃,官方推荐使用类型限定来解决上面的问题,本质上就是使用隐式参数进行隐式转换。
|
||||
Scala2.11+后,视图界定被标识为废弃,官方推荐使用类型限定来解决上面的问题,本质上就是使用隐式参数进行隐式转换。
|
||||
|
||||
```scala
|
||||
object Pair extends App {
|
||||
|
Loading…
x
Reference in New Issue
Block a user