Scala 的那些奇怪的符号 (一):“<:” 和 “>:” 作用及用法
2016-07-29 18:21
423 查看
Scala的语法很多,有些人认为过于繁琐,有些人却认为正是因为繁琐,所以才让这门语言严谨和强大。
例如在翻阅Scala资料或者查看Scala源码的时候,经常会看到“<:”和“>:”,这是什么鬼?下面我就来探讨一下这两个符号的用法:
我们定义了一个子类:“Animal”
然后 ,还有Animal 的一个子类 “Bird”
最后,又定义了一个函数:
乍一看:这tm是什么鬼?“<:”是什么意思?
其实, 这属于Scala泛型中的知识:上边界和下边界。上边界是“<:”,下边界是“>:”;T <: Animal的意思是:T必须是Animal的子类。这样一来,我们再看看这个函数的意思:定义了一个叫“biophony”的函数,这个函数的参数必须传一个集合,一个什么样的集合呢?Animal 子类或者是Animal的集合(包含Animal)。函数右边就很好理解了,map中每个元素调用了sound方法。
知道了是什么之后,接着调用就很简单了:
这样一来就输出:
bird sounds
bird sounds
完美!
假如因为可以包含Animal所以,这么调用也可以:
输出:
animal sound
animal sound
甚至可以一个Animal,一个Bird,多态嘛!
输出:
animal sound
bird sounds
但是,这样就不可以了:
输出:
报错!
Scala的定义了一个“界限”来规定泛型可以适用的在继承关系中的范围,“<:”是上限,表示不超过XXX
不对这怎么还报红了呢?细细想来,Animal的父类的话,不能确定能不能有sound()方法呀,因为父类太多了,Object还是呢。报错也正常,我们就直接返回 things吧
好了,这下好了,不报红了,我们传一个Animal的父类“Earth”的队列,然后没个元素调用“sound()”方法
输出:
hello !
hello !
之前的结论,调用Animal也应该是可以的:
输出:
animal sound
animal sound
好的,也是正确的。假如我们传Animal子类Bird看看会不会报错
输出:
bird sounds
bird sounds
居然不报错!还运行了!这是怎么回事??
我们看一下传Bird后的返回值是什么:
是Animal !真相大白了,由于Bird是子类,Scala把Bird当做Animal来处理了。也就是说,“>:”的时候,传任何参数都可以,但是返回值回有所不同,Animal的子类都会统一按照Animal来处理!
那我们传一个和Animal毫不相关的类,会出现什么情况呢?
写了一个Moon,然后按照如下文传参调用
不报错!
我们看一下返回值:
Object!Scala把它看做了Object。也就是说,可以随便传!只不过和Animal直系的,是Animal父类的还是父类处理,是Animal子类的按照Animal处理,和Animal无关的,一律按照Object处理!
例如在翻阅Scala资料或者查看Scala源码的时候,经常会看到“<:”和“>:”,这是什么鬼?下面我就来探讨一下这两个符号的用法:
“<:”符号
我们定义一个类:“Earth”class Earth { def sound(){ println("hello !") } }
我们定义了一个子类:“Animal”
class Animal extends Earth{ override def sound() ={ println("animal sound") } }
然后 ,还有Animal 的一个子类 “Bird”
class Bird extends Animal{ override def sound()={ print("bird sounds") } }
最后,又定义了一个函数:
defbiophony[T <: Animal](things: Seq[T]) = things map (_.sound)
乍一看:这tm是什么鬼?“<:”是什么意思?
其实, 这属于Scala泛型中的知识:上边界和下边界。上边界是“<:”,下边界是“>:”;T <: Animal的意思是:T必须是Animal的子类。这样一来,我们再看看这个函数的意思:定义了一个叫“biophony”的函数,这个函数的参数必须传一个集合,一个什么样的集合呢?Animal 子类或者是Animal的集合(包含Animal)。函数右边就很好理解了,map中每个元素调用了sound方法。
知道了是什么之后,接着调用就很简单了:
biophony(Seq(new Bird, new Bird))
这样一来就输出:
bird sounds
bird sounds
完美!
假如因为可以包含Animal所以,这么调用也可以:
biophony(Seq(new Animal, new Animal))
输出:
animal sound
animal sound
甚至可以一个Animal,一个Bird,多态嘛!
biophony(Seq(new Animal, new Bird))
输出:
animal sound
bird sounds
但是,这样就不可以了:
biophony(Seq(new Earth, new Earth))
输出:
报错!
Scala的定义了一个“界限”来规定泛型可以适用的在继承关系中的范围,“<:”是上限,表示不超过XXX
“>:”符号
我们把“<:”换成了“>:”defbiophony[T >: Animal](things: Seq[T]) = things map (_.sound())
不对这怎么还报红了呢?细细想来,Animal的父类的话,不能确定能不能有sound()方法呀,因为父类太多了,Object还是呢。报错也正常,我们就直接返回 things吧
def biophony[T >: Animal](things: Seq[T]) = things
好了,这下好了,不报红了,我们传一个Animal的父类“Earth”的队列,然后没个元素调用“sound()”方法
biophony(Seq(new Earth, new Earth)).map(_.sound())
输出:
hello !
hello !
之前的结论,调用Animal也应该是可以的:
biophony(Seq(new Animal, new Animal)).map(_.sound())
输出:
animal sound
animal sound
好的,也是正确的。假如我们传Animal子类Bird看看会不会报错
biophony(Seq(new Bird, new Bird)).map(_.sound())
输出:
bird sounds
bird sounds
居然不报错!还运行了!这是怎么回事??
我们看一下传Bird后的返回值是什么:
是Animal !真相大白了,由于Bird是子类,Scala把Bird当做Animal来处理了。也就是说,“>:”的时候,传任何参数都可以,但是返回值回有所不同,Animal的子类都会统一按照Animal来处理!
那我们传一个和Animal毫不相关的类,会出现什么情况呢?
class Moon { }
写了一个Moon,然后按照如下文传参调用
biophony(Seq(new Moon, new Moon))
不报错!
我们看一下返回值:
Object!Scala把它看做了Object。也就是说,可以随便传!只不过和Animal直系的,是Animal父类的还是父类处理,是Animal子类的按照Animal处理,和Animal无关的,一律按照Object处理!
相关文章推荐
- 配置用户通过Telnet登录设备
- Javascript算法练习(六)
- Bug分支
- NDK相关组件及作用
- RecyclerView的使用(一)
- 删除As low as 价格
- 四元数 (Quaternion)和旋转 的关系
- JAVA设计模式--状态模式
- 分支管理策略
- opencv版本记录
- 希尔排序算法
- android developer tiny share-20160729
- android developer tiny share-20160729
- Leetcode 62. Unique Paths (Medium) (cpp)
- 在eclipse中启动服务器报ERROR:transport error 202 ...ERROR: JDWP Transport dt_socket failed to initialize...
- spark读取redis数据(交互式,scala单机版,java单机版)
- 总结下C语言中的文件读取
- 解决冲突
- EasyUI 数字框
- Rescue