和Java一样,你可以把一个class声明为final,这样它就不能被extends. You can also declare individual methods or fields final so that they cannot be overridden.
object Main extends App
{
var b = new B
println(b)
println(b.go("home"))
//***********************************************************
/**
* 下面这个在平时开发中基本不用,因为最好使用patternMatch
*/
if(b.isInstanceOf[A])//an object of class A or its subclass (such as B),等同于Java的obj instanceof Cl
{
var a = b.asInstanceOf[A]//等同于(Cl) obj
println(s"是A类型或者它的子类型" )
}
if(b.getClass == classOf[A])//scala.Predef.classOf,这个方法等价于Java里面的Cl.class
{
println("是A类型(但不是它的子类型)")
}
//************************************************************最好使用这种
b match {
case a: A => println("是A或者它的子类型")
case _ => println("不是A")
}
}
class A
{
def w = "a"
def go(where : String) = "A go to " + where
}
class B extends A
{
//def w = "w" 没有override会报错
def go() = "go B"
override def go(where : String) = super.go(where)+" B go to "+where//注意怎么调用父类的方法
override def toString = s"${getClass.getName}"//one.two.three.B
}
protected成员(和Java有些区别,它不具有包可访问性)
Unlike in Java, a protected member is not visible throughout the package to which the class belongs.
当然也有a protected[this] variant ,它会限制只有current object可以访问这个变量,这个和private[this]类似
父类的构造函数
an auxiliary constructor can never invoke a superclass constructor directly. The auxiliary constructors of the subclass eventually call the primary constructor of the subclass. Only the primary constructor can call a superclass constructor.
注意下面的继承关系实际是包含两层含义:第一是继承关系,第二是子primary constructor里面调用了父的primary constructor
class Employee(name: String, age: Int, val salary : Double) extends Person(name, age)
Overriding val, def, and var
• A def can only override another def.
• A val can only override another val or a parameterless def.
• A var can only override an abstract var
常见的用法如下:
abstract class Person {
def id: Int // Each person has an ID that is computed in some way
...
}
class Student(override val id: Int) extends Person
// A student ID is simply provided in the constructor
Abstract Classes
abstract class Person(val name: String)
{
/*
*1. No method body—this is an abstract method
2. 和Java不一样,在Scala中,我们不需要为抽象方法增加abstract,我们只需要忽略它的body即可
*/
def id: Int
}
class Employee(name: String) extends Person(name)
{
def id = name.hashCode // 注意override 关键字是可选的 ;: Int也是可选的
}
Abstract Fields
An abstract field 即一个没有初始值的field
abstract class Person
{
val id: Int // No initializer—this is an abstract field with an abstract getter method
var name: String // Another abstract field, with abstract getter and setter methods
}
class Employee(val id: Int) extends Person
{
// Subclass has concrete id property
var name = "Employee " // and concrete name property
}
//匿名类
println(new Person
{
val id=5
var name="hello"
override def toString = "I am anonymous Person"
})
构造顺序
注意: you should not rely on the value of a val in the body of a constructor.
Java中也有类似的问题:In Java, you have a similar issue when you call a method in a superclass constructor. The method might be overridden in a subclass, and it might not do what you want it to do.
解决方法是使用“early definition syntax” in the subclass
The “early definition” syntax lets you initialize val fields of a subclass before the superclass is executed
非预期的输出:
object Main extends App
{
var ant = new Ant
println(s"range is ${ant.range}, evn size is ${ant.env.length}")//打印長度是0
}
class Creature
{
val range: Int = 10
val env: Array[Int] = new Array[Int](range)
}
class Ant extends Creature
{
override val range = 2
}
修改方法:修改Ant类,则长度打印变成了2
class Ant extends {override val range = 2} with Creature //有個with,另外把override移到這裡來了
{
}
*********************************************************Scala的类继承体系
-
AnyRef类编译成Java虚拟机后变成了java.lang.Object类
-
AnyVal and AnyRef 继承自Any class, the root of the hierarchy,Any类型定义了isInstanceOf, asInstanceOf, equals(other: Any)和hashCode方法
3.Null类型:Null 类型的唯一实例是 null,它是所有types的subtype. You can assign null to any reference, but not to one of the value types. For example, setting an Int to null is not possible.
Object Equality
注意equals和hashCode要同步提供,另外hashCode要使用的字段应对同equals使用的字段
class Item(val description: String, val price: Double)
{
/*
* 要注意和Java不一样的地方:In an application program, you don’t generally call eq or equals. Simply use the
== operator. For reference types, it(指的是==操作) calls equals after doing the appropriate check
for null operands.
* */
final override def equals(other : Any) = other match
{
case o:Item => o.description == this.description && o.price == this.price
case _ => false
}
//##是方法,即##()方法调用,等价于x.hashCode except for boxed numeric types and null
//The ## method is a null-safe version of the hashCode method that yields 0 for null instead of throwing an exception.
final override def hashCode = (description, price).##
}
测试:
println(new Item("hello1",3) == new Item("hello1",3))//true
注意:The hash code should be computed only from the fields that you use in the equality check
Value Classes
//1.只能有一个val 修饰的field
//2.且必须继承自AnyVal
//3.没有其他的field或者构造函数
class F(val a : Int) extends AnyVal
{
}
val m = new F(3)
println(m.a)
//这个new不会新生成一个对象,而是使用了它唯一的field,即这里的8
val n = new F(8)
println(n.a)
网友评论