标签:String val Scala Member new class name
1 简单类和无参方法
类的定义可以通过class关键字实现,如下:
package unit7 class Dog { private var leg = 4 def shout(content: String) { println(content) } def currentLeg = leg } |
使用这个类:
val dog = new Dog dog shout "汪汪汪" println(dog currentLeg) |
尖叫提示:在Scala中,类并不声明为Public,一个Scala源文件可以包含多个类。所有这些类都具有公有可见性。调用无参方法时,可以加(),也可以不加;如果方法定义中不带括号,那么调用时就不能带括号。
2 Getter Setter方法
对于scala类中的每一个属性,编译后,会有一个私有的字段和相应的getter、setter方法生成:
//getter println(dog leg) //setter dog.leg_=(10) println(dog currentLeg) |
当然了,你也可以不使用自动生成的方式,自己定义getter和setter方法
class Dog2 { private var _leg = 4 def leg = _leg def leg_=(newLeg: Int) { _leg = newLeg } } |
使用之:
val dog2 = new Dog2 dog2.leg_=(10) println(dog2.leg) |
尖叫提示:自己手动创建变量的getter和setter方法需要遵循以下原则:
1) 字段属性名以“_”作为前缀,如:_leg
2) getter方法定义为:def leg = _leg
3) setter方法定义时,方法名为属性名去掉前缀,并加上后缀,后缀是:“leg_=”,如例子所示
3 对象私有字段
变量:workDetails在封闭包professional中的任何类中可访问。
封闭包:friends的任何类都可以被society包中任何类访问。
变量:secrets只能在实例方法的隐式对象(this)中访问。
package unit7 package society { package professional { class Executive { private[professional] var workDetails = null private[society] var friends = null private[this] var secrets = null def help(another: Executive) { println(another.workDetails) // println(another.secrets) 报错:访问不到 } } } } |
4 Bean属性
JavaBeans规范定义了Java的属性是像getXXX()和setXXX()的方法。许多Java工具都依赖这个命名习惯。为了Java的互操作性。将Scala字段加@BeanProperty时,这样的方法会自动生成。
1) 创建一个Bean,使用@BeanProperty注解标识某个属性变量
package unit7 import scala.beans.BeanProperty class Person { @BeanProperty var name: String = _ } |
2) 通过getName、setName访问属性
val person = new Person person.setName("Nick") person.getName println(person.name) |
尖叫提示:
Person将会生成四个方法:
--name:String
--name_=(newValue:String): Unit
--getName():String
--setName(newValue:String):Unit
5 构造器
scala中构造分为主构造器和辅助构造器
1) 主构造的参数直接放置于类名之后
定义类: class ClassConstructor (var name: String, private var price: Double){ def myPrintln = println(name + "," + price) } 执行: val classConstructor = new ClassConstructor("《傲慢与偏见》", 20.5) classConstructor.myPrintln |
2) 主构造器会执行类定义中的所有语句
定义类: class ClassConstructor2(val name: String = "", val price: Double = 0) { println(name + "," + price) } 执行: val classConstructor2 = new ClassConstructor2("aa", 20) val classConstructor2_2 = new ClassConstructor2() |
3) 通过private设置的主构造器的私有属性
4) 如果不带val和var的参数至少被一个方法使用,该参数将自动升级为字段,这时,name和price就变成了类的不可变字段,而且这两个字段是对象私有的,这类似于 private[this] val字段的效果。
否则,该参数将不被保存为字段,即实例化该对象时传入的参数值,不会被保留在实例化后的对象之中。
主构造器参数 | 生成的字段/方法 |
name: String | 对象私有字段。如果没有方法使用name, 则没有该字段 |
private val/var name: String | 私有字段,私有的getter和setter方法 |
var name: String | 私有字段,公有的getter和setter方法 |
@BeanProperty val/var name: String | 私有字段,公有的Scala版和Java版的getter和setter方法 |
如果想让主构造器变成私有的,可以在()之前加上private,这样用户只能通过辅助构造器来构造对象了
class Person private () {...} |
5) 辅助构造器名称为this,通过不同参数进行区分,每一个辅助构造器都必须以主构造器或者已经定义的辅助构造器的调用开始
class Person { private var name = "" private var age = 0 def this(name: String) { this() this.name = name } def this(name: String, age: Int) { this(name) this.age = age } def description = name + " is " + age + " years old" } |
6 嵌套类
即,在class中,再定义一个class,以此类推。
Java中的内部类从属于外部类。Scala中内部类从属于实例。
1) 创建一个嵌套类,模拟局域网的聊天场景
import scala.collection.mutable.ArrayBuffer //嵌套类 class Network { class Member(val name: String) { val contacts = new ArrayBuffer[Member] } private val members = new ArrayBuffer[Member] def join(name: String) = { val m = new Member(name) members += m m } } |
2) 使用该嵌套类
//创建两个局域网 val chatter1 = new Network val chatter2 = new Network //Fred 和 Wilma加入局域网1 val fred = chatter1.join("Fred") val wilma = chatter1.join("Wilma") //Barney加入局域网2 val barney = chatter2.join("Barney") //Fred将同属于局域网1中的Wilma添加为联系人 fred.contacts += wilma //fred.contacts += barney //这样做是不行的,Fred和Barney不属于同一个局域网,即,Fred和Barney不是同一个class Member实例化出来的对象 |
在Scala中,每个实例都有它自己的Member类,就和他们有自己的members字段一样。也就是说,chatter1.Member和chatter2.Member是不同的两个类。也就是所谓的:路径依赖类型,此处需要详细解释之。
如果想让members接受所有实例的Member,一般有两种办法:
1) 将Member作为Network的伴生对象存在
创建类:
import scala.collection.mutable.ArrayBuffer // 伴生对象 class Network2 { private val members = new ArrayBuffer[Network2.Member] def join(name: String) = { val m = new Network2.Member(name) members += m m } def description = "该局域网中的联系人:" + (for (m <- members) yield m.description).mkString(", ") } object Network2 { class Member(val name: String) { val contacts = new ArrayBuffer[Member] def description = name + "的联系人:" + (for (c <- contacts) yield c.name).mkString(" ") } } |
使用:
val chatter3 = new Network2 val chatter4 = new Network2 //Fred 和 Wilma加入局域网1 val fred2 = chatter3.join("Fred") val wilma2 = chatter3.join("Wilma") //Barney加入局域网2 val barney2 = chatter4.join("Barney") //Fred将同属于局域网3中的Wilma添加为联系人 fred2.contacts += wilma2 //Fred将不同属于局域网3中,属于局域网4中的的Wilma添加为联系人 fred2.contacts += barney2 println(chatter3.description) println(chatter4.description) println(fred2.description) println(wilma2.description) println(barney2.description) |
2) 使用类型投影,注意留意关键符号:“#”
创建类:
import scala.collection.mutable.ArrayBuffer //投影 class Network3 { class Member(val name: String) { val contacts = new ArrayBuffer[Network3#Member] } private val members = new ArrayBuffer[Member] def join(name: String) = { val m = new Member(name) members += m m } } |
使用:
val chatter5 = new Network3 val chatter6 = new Network3 //Fred 和 Wilma加入局域网1 val fred3 = chatter5.join("Fred") val wilma3 = chatter5.join("Wilma") //Barney加入局域网2 val barney3 = chatter6.join("Barney") fred3.contacts += wilma3 |
尖叫提示:与Java一样,在嵌套类中,如果想得到外部类的实例化对象的引用,可以使用“外部类.this”的方式得到。
标签:String,
val,
Scala,
Member,
new,
class,
name
From: https://blog.51cto.com/u_12654321/5845155