从 Java 到 Scala(一):面向对象谈起
去年我加入水滴团队,面试中,面试官问:"你了解 Scala 吗?"
"不了解(尴尬)。"
"你知道 Spark 吗?它就是使用 Scala 编写的,不过在我们团队中,Scala 主要作为后端语言,我们 90% 以上的业务代码都是使用 Scala 编写。Scala 在国内使用的比较少,但是在国外用的还是蛮多的,如 Twitter 就是使用 Scala 写的后端。"
自那以后,我便开始了 Scala 的学习之旅。
Scala 是由德国的计算机科学家和编程方法教授 Martin Odersky 设计出来的,它的设计原理严格遵循数学的逻辑推理。因此它是一门优秀的编程语言,它不仅仅在工业界被广泛使用,在学术界也占用很高的研究地位。
由于之前的 Java 背景,我经常拿 Scala 与 Java 这两门语言比较。 Scala 和 Java 都基于 JVM,因此 Java 的类库,Scala 都可以直接使用。但是我对 Scala 印象最深的点,并不是「面向对象」,而是它还拥抱「函数式」,尤其是它的「高阶」。
如果我们把「面向对象」比作站在地面上观察事物的原理,并且使用这些原理解决问题,那么「高阶」就是让你站在山上去看待事物,对问题进行更高层次的抽象。
因此不管是解决实际问题,还是提高对编程语言的认知,Scala 都是一们值得学习的语言。
我是从《快学 Scala》这本书开始学习 Scala 的,受此书启发,我想能不能书写一个「从 Java 到 Scala 系列」,寻找一棵从 Java 通往 Scala 的连续的知识树,通过对知识树的讲解,来学习 Scala。
好了,这就是本系列的第一篇,那么我们如何谈起呢?
既然 Java 和 Scala 都是「面向对象」的,那我们就来探索一下什么是「面向对象」吧。
模板和对象
「模板」是在代码层面描述一类对象的「行为」或者「状态」的代码,它是抽象的。如 Java 中的类,C 语言中的结构体,它们都是「模板」。
「对象」是在运行期间通过模板在内存中生成的一个个实体,它是具体的。如 Java 在运行期间通过 new 在内存中产生的实体就叫做「对象」。
如果你说共享单车,那么它就是一个「模板」;如果你说这辆共享单车和那辆共享单车,那它们就是「对象」。
在代码层面,「对象」的行为可以定义为「方法」,「对象」的状态可以定义为「属性」,那我们如何去描述一类「对象」的方法或者属性呢?-封装。
例如共享单车,它有车轮,二维码等属性,有开锁和关锁等行为。那么我们可以有三种方式来封装共享单车。
基于对象的封装
这种方式就是直接封装,最典型的例子就是 C 语言中的结构体。
封装共享单车的「模板」如下:
1 2 3 4 5 6 |
struct SharedBicycle{ 车轮; 二维码; 开锁; 关锁; }; |
基于类的封装
大多数「面向对象」的语言,如 Java,Scala,C++等,都使用这种方式封装,「模板」如下:
1 2 3 4 5 6 |
class SharedBicycle{ 属性:车轮; 属性:二维码; 方法:开锁; 方法:关锁; } |
基于原型的封装
JavaScript 就是使用这种封装方式,「模板」如下:
1 2 3 4 5 6 7 |
function SharedBicycle(){ this.车轮 = xxx; this.二维码 = xxx; } //添加原型方法 SharedBicycle.prototype.开锁 = function(){...}; SharedBicycle.prototype.关锁 = function(){...}; |
纯面向对象
我们已经得知,可以用多种实现面向对象的不同技术,那么什么是纯面向对象的语言呢?
我们知道 Java 是一门「面向对象」的语言,那么在 Java 中是否真的「万物皆对象」?
在 Java 中,我们可以写这么一段代码 int a = 3; 然后我们发现 a 并没有封装任何的属性或者方法。
因此我们可以说 a 不是一个「对象」,Java 不是一门「纯粹面向对象」的语言。
再看看 Scala ,不论是低阶的 Int,Double,还是高阶类型,都封装有属性或者方法,因此 Scala 才是一门「纯粹面向对象」的语言。
那么是什么支持 Scala 一切皆为「对象」的呢?-Scala 的通用类型系统。
Scala 通用类型系统
顶类型
我们知道,在 Java 中,所有「对象」的「顶类型」都是 java.lang.Object,但是 Java 却忽略了 int,double等 JVM 「原始类型」,它们并没有继承 java.lang.Object。
但是在 Scala 中,存在一个通用的「顶类型」- Any。
Scala 引入了Any 作为所有类型共同的顶类型。Any 是 AnyRef 和 AnyVal 的超类。
AnyRef 面向 Java(JVM)的对象世界,它对应 java.lang.Object ,是所有对象的超类。
AnyVal 则代表了 Java 的值世界,例如 int 以及其它 JVM 原始类型。
正是依赖这种继承设计,我们才能够使用 Any 定义方法,同时兼容 scala.int 以及 java.lang.String 的实例。
1 2 3 4 5 6 7 8 9 |
class Person val allThings = ArrayBuffer[Any]() val myInt = 42 // Int, kept as low-level `int` during runtime allThings += myInt // Int (extends AnyVal) allThings += new Person() // Person (extends AnyRef), no magic here |
正是通过这种「通用类型系统」的设计,使得 Scala 摆脱「原始类型」这种边缘情况的纠缠,从而实现「纯粹的面向对象」。
说完了「顶类型」,我们再来看看「底类型」。
底类型
我们知道在 Java 中比较闹心的就是异常处理,当我们调用一个抛出异常的方法,我们必须抛出或者处理异常。
但是在 Scala 中,我们知道一切表达式皆有类型,难道「抛异常」也是有类型的?
1 2 |
scala> val a = Try(throw new Exception("123")) a: scala.util.Try[Nothing] = Failure(java.lang.Exception: 123) |
我们发现「抛异常」竟然是 Nothing 类型,在 Scala 中,难道 Nothing 仅仅是作为「抛异常」的类型?
1 2 3 4 5 6 7 8 |
scala> def fun(flag:Boolean)={ if(flag){ 1 // Int }else{ throw new Exception("123") //Nothing } } fun: (flag: Boolean)Int |
我们发现 fun 函数并没有报错,而且返回值类型竟然是 Int,这让我们有一个大胆的猜测:Nothing 是 Int 的子类型。
1 2 |
[Int] -> ... -> AnyVal -> Any Nothing -> [Int] -> ... -> AnyVal -> Any |
其实在 Scala 中, Nothing 不仅仅是 Int 的子类型,它更是所有类型的子类型。 这让我们又产生了一个大胆的猜测:难道 Nothing 继承了所有的类型?咳咳,这个问题我们以后在讨论。
在 Scala 中,还有一个类型 Null 遵循着和 Nothing 一样的原理。
1 2 3 4 5 6 7 8 |
scala> def fun2(flag:Boolean)={ if(flag){ "123" //String }else{ null //Null } } fun2: (flag: Boolean)String |
同理,我们可以得出 Null 是 String的子类型
1 2 |
[String] -> AnyRef -> Any Null -> [String] -> AnyRef -> Any |
那我们看看 Null 是否可以兼容 Int。
1 2 3 4 5 6 7 8 |
scala> def fun3(flag:Boolean)={ if(flag){ 123 //Int }else{ null //Null } } fun3: (flag: Boolean)Any |
我们发现 fun3 的返回值类型竟然是 Any,说明 Null 不能兼容 Scala 的「值类型」,其实从 Scala 的帮助手册中我们就可以得出结论:Null 是所有引用类型的子类型
1 |
abstract final class Null extends AnyRef |
正因如此,fun3 的返回值类型才是 Any,因为 Any 才是 AnyVal 和 AnyRef 公共的超类。
总结
本文以面向对象为引子,找到了一个 Java 和 Scala 共有的知识节点,从而引出 Scala 的通用类型系统。那么在下一篇文章中,我们由此展开进一步思考,到底什么是所谓的「类型」,以及 Scala 在类型方面存在哪些与 Java 不同的有趣的地方。
本文转载自:https://scala.cool/2018/03/java-2-scala-1/
从 Java 到 Scala(一):面向对象谈起相关推荐
- 2018年第44周-scala入门-面向对象基础语法
scala和java都是可以运行在JVM上, 所以scala和java是可以互相调用, 那么问题来了, 既然已经有java语言存在, 为什么还要发明scala语言. 存在即合理, 所以我就想找下sca ...
- Java进阶学习-7 面向对象程序设计原则
title: Java进阶学习-7 面向对象程序设计原则 date: 2020-02-02 18:02:27 tags: 以一个城堡游戏为例子谈面向对象程序设计原则 Game.java package ...
- Scala深入浅出——从Java到Scala
本文适合有一定Java基础的,并想系统学习Scala的小伙伴借鉴学习.文章有大量实例,建议自己跑一遍. Scala深入浅出--从Java到Scala Scala 一.介绍 1.什么是Scala? 2. ...
- scala linux 环境配置,LINUX系统下Java和Scala的环境配置
最近,笔者在研究一个有关"自然语言处理"的项目,在这个项目中,需要我们用Spark进行编程.而Spark内核是由Scala语言开发的,所以在使用Spark之前,我们必须配置好Sca ...
- 从 Java 到 Scala,再到 Kotlin
在 Java 之后,JVM 平台上出现了一些其他的编程语言,Scala 和 Kotlin 可以算是其中的佼佼者.Scala 已成为大数据领域的明星,Kotlin 在 2017 年 Google IO ...
- 大数据入门:Java和Scala编程对比
在学习大数据之初,很多人都会对编程语言的学习有疑问,比如说大数据编程主要用什么语言,在实际运用当中,大数据主流编程是Java,但是涉及到Spark.Kafka框架,还需要懂Scala.今天的大数据入门 ...
- spark需要maven管理吗_Spark-Maven全新安装:如何同时编译Java和Scala类
我有一个Spark项目,其中同时包含.scala和.java文件.我正在尝试通过Maven构建来编译这两种类型的类.但是,当我运行" mvn clean install"时,它只会 ...
- Akka 系列(五):Java 和 Scala 中的 Future
随着CPU的核数的增加,异步编程模型在并发领域中的得到了越来越多的应用,由于Scala是一门函数式语言,天然的支持异步编程模型,今天主要来看一下Java和Scala中的Futrue,带你走入异步编程的 ...
- Java、Scala和Go语言多线程并发对比测试
2019独角兽企业重金招聘Python工程师标准>>> 本文试图记录下对流行的Java.Scala和Go语言多线程并发对比测试,作为未来项目选择开发语言的一个参考. 具体的语言对比测 ...
最新文章
- 计算机视觉系统怎样剖析“看到”的一切?
- 查看apache、linux、kernel、nginx等版本
- HDU-1316 How Many Fibs? Java
- String,StringBuffer和StringBuilder的区别
- 为什么大多数人宁愿吃生活的苦,也不愿吃学习的苦?
- Makefile:自动化变量 $@,$^,$<,$?
- (Mybatis)Mybatis简介和初步使用
- 牛客题霸 NC7 买卖股票的最好时机
- 用vue实现模态框组件
- php 分享微博,php微信分享到朋友圈、QQ、朋友、微博
- STM32中GPIO_Mode--GPIO配置
- ASP.NET 状态视图概览
- Hadoop JobTracker和NameNode运行时参数查看
- 跨部门的bug的沟通
- c语言 入字符要中文状态吗,常见的HTTP状态码深入理解
- 《缠中说禅108课》30:缠中说禅理论的绝对性
- 机器学习入门系列05,Classification: Probabilistic Generative Model(分类:概率生成模型)
- ArcGis制作三维地形图教程
- 自己接软件项目,如何报价??
- 在智能制造背景下,传统工厂何去何从?
热门文章
- 顶会快讯|5篇AAAI2020相关论文抢先看(附GitHub代码地址)
- NN如何在表格数据中战胜GBDT类模型
- 资讯|WebRTC M92 更新
- 2020 年值得再读一遍的网易云信技术干货 | 上篇
- 0228互联网新闻 | 抖音新推营销产品“抖店”;iTutorGroup牵手机器人索菲亚开创“新双师”模式...
- 那些2019年会爆发的泛娱乐黑科技风口——网易MCtalk泛娱乐创新峰会揭秘
- 小程序完整对接 pingpp支付
- 王晖:以Linux为核心扩展云核心组件
- asp.net 服务器控件的 ID,ClientID,UniqueID 的区别
- Dell sc1425安装ESXi 5不成功