标签:
类是对象的模板,通过构造类,能够使用new关键字声明一系列同结构的对象。
Scala的一个源文件可以包含多个public类。
声明Person类:
class Person{
var name : String = _
val age = 10
private[this] val gender = “male”
}
说明:
name字段被赋值为“_”“_”即占位符。表示name被声明为String。但赋值为“_”,即暂不赋实际的值。
若使用占位符,Scala无法判断name的类型,所以必须声明该字段的类型。
gender 在Person中“private[this]” 限定住了,在类的外部无法被调用。
Scala构造器
Scala构造器与Java构造器有很大的不同。Scala中的构造器分为主构造器与副构造器。
主构造器
Scala中每个类都有主构造器,且与类定义交织在一起。
Scala主构造器的参数直接放置在类名之后。
一个类若没有显式定义主构造器,则自动拥有一个无参主构造器。
例:主构造器的声明。
class Person(val name: String, var age: Int) {
// ...
}
Scala类中没有放在方法体的语句都会被执行。
例:主构造器的方法体。
class Person(val name: String, var age: Int) {
println("This is primary constrator!")
}
主构造器的参数被编译成字段,并在构造对象时初始化传入。
例:
object PersonMain{
def main(args: Array[String]) {
val p = new Person("Tom",18);
println("p is "+ p.name + "," + p.age )
}
}
输出:
例:
class Person(val name: String, var age: Int) {
println(“Person is created”)
val id = name + ":" + age
}
val p = new Person(“Tom” , 18)
说明:
Person类拥有三个字段name,age,id 。
主构造器的参数一般有四种:
value: String
对象的不可变私有字段,对象中没有方法使用value,则没有该字段。即相当于private[this] val 。
private val value: String 或 private var value: String
对象的私有字段,私有的getter/setter方法。
val/var value:String
对象的私有字段,公有的getter/setter方法。
@BeanProperty val/var value:String
私有字段,共有的Scala和JavaBean的getter/setter方法
私有主构造器
class HelloWorld private(主构造器){ 类成员 }
主构造器私有,只能通过辅助构造器构造对象。
副构造器(辅助构造器)
Scala类能有任意多的副构造器。
Scala的副构造器都以“this”为名称,在类中定义。
例:
class Person(var name: String, val age: Int) {
println("this is primary constrator!")
var gender: String = _
def this(name: String, age: Int, gender: String) {
this(name, age)
this.gender = gender
}
}
输出:
副构造器中必须调用主构造器或调用其他副构造器,而其他副构造器中必须调用主构造器。也即所有副构造器中必须有一个调用主构造器。
录:
class HelloWorld{
private var value1 = ””
private var value2 = ””
def this(m:String) {
this() //调用主构造器
this.value1=m
}
def this(m:String,n:String) {
this(m) //调用已定义的辅助构造器
this.value2=n
}
}
辨析:构造器与函数
主构造器的参数允许带有val/var关键字,函数的参数不能带有这些关键字。
主构造器的参数允许带有val/var关键字,副构造器的参数不能带有这些关键字。
Scala中没有static的概念。但Scala中使用object提供类似的功能。
单例对象
object语法定义了的类的单实例。
object Accounts{
private var lastNum = 0
def newUniqueNum = {
lastNum += 1
lastNum
}
}
object中的方法,即可以被当作为静态方法。
调用object中的方法,直接调用,不用new。
Accounts.newUniqueNum ()
对象的构造器在该对象第一次被使用时调用。
object语法结构与class大致相同,除了object不能提供构造器参数。
通常使用单例对象的环境:
作为存放工具函数或常量的地方。
共享单个不可变实例。
利用单个实例协调某个服务。
伴生对象
Java中存在既有实例方法又有静态方法的类。在Scala中可以通过类与类的伴生对象来达到同样的目的。
当一个单例对象存在同名类的时候,称为伴生对象。
class Account{...} //伴生类
object Account{...} //伴生对象
类和其伴生对象可以互相访问私有属性,但必须存在同一个源文件中。
类的伴生对象可以被访问,但并不在作用域中。
例:
class Account{...}
object Account{ def newUniqueNum = {...} }
HelloWorld类必须通过Account.newUniqueNum()调用伴生对象中的newUniqueNum()方法,而不能直接用newUniqueNum()来调用。
伴生对象也是扩展类功能的一种途径。因为伴生类可以直接使用伴生对象的方法。
apply方法
apply方法专用于简化创建类实例的方法。apply方法类似于工厂方法。当需要构造有参数需求的伴生对象时,通常会定义和使用对象的apply方法。apply方法返回伴生类的对象。
当遇到如下形式的表达式时,apply方法就会被调用:Object(参数1, ... ,参数N)
例:Spark源码中Graph对象。
GraphImpl方法也是一个Object对象。
例:Array对象定义了apply方法,则可以用如下表达式来创建数组:
Array(“Mary”,”had”,”a”,”little”,”lamb”)
辨析:
Array(100) 返回的是拥有1个元素的数组。元素值为100。
new Array(100) 返回的是拥有100个元素的数组。每个元素值为null。
例:
class ApplyOperation{}
class ApplyTest{
def haveTry{
println(“Have a try on apply!”)
}
}
object ApplyTest{
def apply() = new ApplyTest
}
object ApplyOperation extends App {
val a = ApplyTest()
a.haveTry
}
例:
class HelloWorld(var m:String,n:Char){...}
object HelloWorld{
def apply(n:Char)=new HelloWorld(“ ”,n)
}
val hi=HELLOWORLD(‘j’)
例:
class Account private(val id:Int,initialBalance:Double){
private var balance = initialBalance
}
object Account{
def apply(initialBalance:Double) = new Account(newUniqueNum ,initialBalance)
}
构造账号对象:
val acct = Account(1000.0)
class中使用apply方法
apply方法一般只使用于object。class中也可以使用,但不常用。
例:
class ApplyOperation{}
class ApplyTest{
def apply() = "apply in class"
def haveTry{
println("Have a try on apply!")
}
}
object ApplyTest{
def apply() = new ApplyTest
}
object ApplyOperation extends App {
val a = new ApplyTest
val applyStr = a();
println(applyStr)
}
输出:
继承是类的拓展。
extends是Scala中实现继承的保留字:
class week extends month{...}
说明:
week类继承了month类所有非私有成员。
week类是month类的子类,month类是week类的超类。
子类能重写超类的成员(具有相同名称和参数)。
例:
class Student(name:String , age:Int ,val major : String) extends Person(name , age) {
println(“this is subclass of Person , major is :” + major)
}
单例对象同样能从类中继承,与类的继承语法相同:
object day extends week{...}
单例对象是否能被继承呢?
重写
Scala中使用override保留字进行方法、字段重写
class week extends month{
override def firstday = {...}
}
override保留字实际使用类似与private,声明这个保留字后的定义、声明是对超类的重写,因此,其也可以写在类定义的参数中
class week(override val lastday:String) extends month{...}
子类的重写或修改Scala会检查其超类,但是,超类的修改并不会检查其子类
例:
class Student(name:String , age:Int ,val major : String) extends Person(name , age) {
println(“this is subclass of Person , major is :” + major)
override def toSting = “override toSting”
}
重写包括字段和方法,但参数不同的方法可以不重写
class month{ def secondday(m:String)={...}}
class week extends month{ def secondday ={...}}
规则:
重写 def
用val :利用val能重写超类用没有参数的方法(getter)
用def:子类的方法与超类方法重名
用var:同时重写getter、setter方法,只重写getter方法报错
重写val
用val:子类的一个私有字段与超类的字段重名,getter方法重写超类的getter方法
重写var
用var:且当超类的var是抽象的才能被重写,否则超类的var都会被继承
例:
class month{
val one = 25 //可在子类中用val重写
var two = 15 //不可在子类中用var重写,因为不是抽象的
var three:Int
def firstday = //可在子类中用val重写
def now = //可在子类中用var重写
def now_ =
def lastday(m:Char)={} //可在子类中用def重写
}
总结:
子类中,def只能重写超类的def,val能重写超类的val或不带参数的def,var只能重写超类中抽象的var或者超类的getter/setter对。
匿名子类
val alien = new Person(“Fred”){
def greeting = “Greetings , Earthling! My name is Fred”
}
标签:
原文地址:http://www.cnblogs.com/shijiaqi1066/p/4608924.html