Scala中的类继承关系
Posted dabokele
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala中的类继承关系相关的知识,希望对你有一定的参考价值。
本章主要从整体层面了解Scala中的类层级关系。
一、Scala的类层级
在Java中Object
类是所有类的最终父类,其他所有类都直接或间接的继承了Object
类。在Scala中所有类的最终父类为Any
类,所以Any
类中的所有方法都可以在Scala中任意类中使用。但是这并不是说Scala中的Any
类就类似于Java中的Object
类,Scala中真正地位类似于Java中Object
类的是AnyRef
类。
在Scala中还提供了两个类Null
和Nothing
,这两个类在整个Scala类层级的最底层,其中Nothing
类是所有类的最终子类,Nothing
类直接或间接继承其他任何类。
1、整体类层级图
下图展示了Scala中的整体类层级图,其中Any
位于最顶端,Nothing
位于最底端。
2、Any类结构
这一节中我们看一下Any
类中定义了哪些方法。
从Scala API文档中可以看到,Any
类中提供==, !=, equals, ##, hashCode, toString, isInstanceOf[TO], asInstanceOf[TO]
共八个方法。其中==, !=, ##, asInstanceOf[TO], isInstanceOf[TO]
是final
类型的,不能在子类中使用override
关键字进行重写。在Scala中对于==
方法,如果判断对象为引用类型,调用该方法等同于调用该对象的equals
方法。
Any
类的两个直接子类是AnyVal
和AnyRef
,其中AnyVal
是Scala中的值类型,比如Double, Float
等的直接父类,注意这里Unit
类型也是AnyVal
类型的直接子类。而AnyRef
则是Scala中所有引用类型类的父类,类似于Java中的Object
类。
二、原始类型是如何实现的
对Java熟悉的话,应该会对int
类型和Integer
类型有一定的了解。在Scala中对Int
类型变量的处理也和Java中类似,Int
类型提供加或乘这样的简单操作,但如果需要调用toString
方法或者将Int
值赋给Any
类型变量时,Int
型变量会自动转化成Integer
类型。这个过程和Java中的自动装箱有些类似。
我们首先看一下下面这段Java代码
boolean isEqualInt(int x, int y)
return x == y;
System.out.println(isEqual(421, 421));
boolean isEqualInteger(Integer x, Integer y)
return x == y;
System.out.println(isEqualInteger(421, 421));
代码在IDEA中的运行结果如下
isEqualInt
方法接收到传入的两个整数后直接判断值是否相等,得到的结果为true
。但是isEqualInteger
方法接收到整型参数后,哪怕是值相等的整型参数,也会首先自动装箱成两个Integer
类型对象,并且两个Integer
对象是不同的对象,调用==
方法得到的结果为false
。
再看一段Scala中的代码,仍然定义两个函数、
def isEqualInt(x: Int, y: Int) = x == y
isEqualInt(421, 421)
def isEqualAny(x: Any, y: Any) = x == y
isEqualAny(421, 421)
运行结果如下,
由于在Scala中,引用类型调用==
方法等同于调用equals
方法,所以isEqualAny
方法的返回结果也是true
。
那么,如果在Scala中就是需要判断两个引用类型对象的引用是否相等,应该怎么办?在AnyRef
类中,Scala提供了eq
,ne
方法。
val x = new String("abc")
val y = new String("abc")
x == y
x eq y
x ne y
运行结果如下,
三、底层类型
这里主要讨论上面的类继承关系图中最底层的两个类scala.Null
和scala.Nothing
。Scala中可以使用者两个类统一的处理一些面向对象编程的边界情况。
1、Null类
比如说在Java中,null
值是没有对应的类型的,如果将某个变量赋值null
然后调用getClass
方法,会报一个NullPointerException
,如下图所示。
但是在Scala中null
值的类型为Null
。Null
类型所有引用类型类的子类,而不是值类型的子类。所以,不能将null
赋值给Int
类型变量。
val i: Int = null
执行结果如下,
2、Nothing类
Nothing
类位于Scala类继承关系中的最底层,是Scala中任何类的子类,包括上面的Null
类。
由于Nothing
类是任何类的子类,所以可以以如下形式来使用该类。
def error(message: String): Nothing =
throw new RuntimeException(message)
def divide(x: Int, y: Int): Int =
if (y != 0) x / y
else error("can't divide by zero")
在前面我们知道了,Scala中的执行语句都有一个返回结果类型,对于if
语句来说,返回类型为两个分支的公共父类,而这里if
分支的返回类型为Int
且Int
是else
的返回类型Nothing
的父类,所以divide
方法的最终返回类型仍然是Int
。
以上是关于Scala中的类继承关系的主要内容,如果未能解决你的问题,请参考以下文章
scala 中 AnyAnyRefObjectAnyVal 关系