面向对象编程之类和对象
定义一个类
1 // 定义类,包含field及方法
2 scala> :paste
3 // Entering paste mode (ctrl-D to finish)
4 class HelloWorld {
5 private var name = "leo"
6 def sayHello() {print("Hello, " + name)}
7 def getName = name
8 }
9 // Exiting paste mode, now interpreting.
10 defined class HelloWorld
11 // 创建类的对象,并调用其方法
12 scala> val helloWorld = new HelloWorld
13 helloWorld: HelloWorld = HelloWorld@380e4452
14 // 如果方法无参,可以不加括号,如果定义方法时不带括号,则调用方法时也不能带括号
15 scala> helloWorld.sayHello()
16 Hello, leo
17 scala> helloWorld.sayHello
18 Hello, leo
19 scala> helloWorld.getName
20 res9: String = leo
21 scala> helloWorld.getName()
22 :14: error: not enough arguments for method apply: (index: Int)Char in class StringOps.
23 Unspecified value parameter index.
24 helloWorld.getName()
25 ^
getter与setter
定义不带private的var field,此时scala生成的面向JVM的类时,会定义为private的name字段,并提供public的getter和setter方法。
而如果使用private修饰field,则生成的getter和setter也是private的。
如果定义val field,则只会生成getter方法。
如果不希望生成setter和getter方法,则将field声明为private[this]。
1 scala> class Student {
2 | var name = "leo"
3 | }
4 defined class Student
5 scala> val s = new Student
6 s: Student = Student@2a88981e
7 // 调用getter和setter方法,分别叫做name和name_=
8 scala> s.name
9 res0: String = leo
10 scala> s.name()
11 <console>:14: error: not enough arguments for method apply: (index: Int)Char in class StringOps.
12 Unspecified value parameter index.
13 s.name()
14 ^
15 scala> s.name = "jack"
16 s.name: String = jack
17 scala> s.name
18 res2: String = jack
19 scala> s.name_ = "jen"
20 <console>:15: error: value name_ is not a member of Student
21 val $ires1 = s.name_
22 ^
23 <console>:13: error: value name_ is not a member of Student
24 s.name_ = "jen"
25 ^
自定义getter与setter
如果只是希望拥有简单的getter和setter方法,那么就按照Scala提供的语法规则,根据需求为field选择合适的修饰符就好:var、val、private、private[this]。
如果希望能够自己对getter与setter进行控制,则可以自定义getter与setter方法。
自定义setter方法的时候一定要注意Scala的语法限制,签名、=、参数间不能有空格。
1 scala> :paste
2 // Entering paste mode (ctrl-D to finish)
3class Student {
4 private var myName = "leo"
5 def name = "your name is " + myName
6 def name_ = (newName:String) {
7 print("you cannot edit your name!")
8 }
9}
10 // Exiting paste mode, now interpreting.
11 <console>:14: error: not found: value newName
12 def name_ = (newName:String) {
13 ^
14 scala> :paste
15 // Entering paste mode (ctrl-D to finish)
16 class Student {
17 private var myName = "leo"
18 def name = "your name is " + myName
19 def name_=(newName:String) {
20 print("you cannot edit your name!")
21 }
22 }
23 // Exiting paste mode, now interpreting.
24 defined class Student
25 scala> val s = new Student
26 s: Student = Student@4fc8cd5c
27 scala> val s = new Student()
28 s: Student = Student@1dafc862
29 scala> s.name
30 res3: String = your name is leo
31scala> s.name = "leo1"
32you cannot edit your name!s.name: String = your name is leo
private[this]的使用
如果将field使用private来修饰,那么代表这个field是类私有的,在类的方法中,可以访问类的其他对象的private field。这种情况下,如果不希望field被其他对象访问到,那么可以使用private[this],意味着对象私有的field,只有本对象内可以访问到。
1 scala> :paste
2// Entering paste mode (ctrl-D to finish)
3 class Student {
4 private var myAge = 0
5 def age_=(newAge:Int) {
6 if(newAge>0) myAge = newAge
7 else println("illegal age!")
8 }
9 def age = myAge
10 def older(s:Student) = {
11 myAge > s.myAge
12 }
13 }
14// Exiting paste mode, now interpreting.
15 defined class Student
16 scala> val s1 = new Student
17 s1: Student = Student@7ba9d3ec
18 scala> s1.age = 20
19 s1.age: Int = 20
20 scala> val s2 = new Student
21 s2: Student = Student@2dd6713
22 scala> s2.age = 25
23 s2.age: Int = 25
24 scala> s1.older(s2)
25 res8: Boolean = false
private[this]的使用,只有本对象内可以访问到。
辅助constructor
Scala中,可以给类定义多个辅助constructor,类似于Java中的构造函数重载,辅助constructor之间可以互相调用,而且必须第一行调用主constructor。
主constructor
Scala中,主constructor是与类名放在一起的,与Java不同,而且类中,没有定义在任何方法或者是代码块之中的代码,就是主constructor的代码,这点感觉没有Java那么清晰。
1 scala> class Student(val name:String, val age:Int) {
2 | println("your name is " + name + ", your age is " + age)
3 | }
4 defined class Student
5 scala> val s = new Student
6 :14: error: not enough arguments for constructor Student: (name: String, age: Int)Student.
7 Unspecified value parameters name, age.
8 val s = new Student
9 ^
10 scala> val s = new Student("leo", 30)
11 your name is leo, your age is 30
12 s: Student = Student@60cdee08
主construntor中还可以通过使用默认参数,来给参数默认的值。
如果主constructor传入的参数什么修饰都没有,比如name:String,那么如果类内部的方法使用到了,则会声明为private[this] name,否则没有该field,就只能被constructor代码使用而已。
内部类
Scala中,同样可以在类中定义内部类,但是与Java不同的是,每个外部类的对象的内部类,都是不同的类。
c2.Student类,c1.Student类,是不同的外部类的实例的不同的类。
object
object,相当于class的单个实例,通常在里面放一些静态的field或者method,第一次调用object的方法时,就会执行object的constructor,也就是object内部不在method中的代码,但是object不能定义接受参数的constructor。
object的constructor只会在其第一次被调用时执行一次,以后再次调用就不会再次执行constructor了。
object通常用于作为单例模式的实现,或者放class的静态成员,比如工具方法。
伴生对象
如果有一个class,还有一个与class同名的object,那么就称这个object是class的伴生对象,class是object的伴生类。伴生类和伴生对象必须存放在一个.scala文件之中,伴生类和伴生对象,最大的特点在于,互相可以访问private field。
object继承抽象类
object的功能和class类似,除了不能定义接收参数的constructor之外,object也可以继承抽象类,并覆盖抽象类中的方法。
apply方法
object中重要的一个特殊方法,apply方法,通常在伴生对象中实现apply方法,并在其中实现构造伴生类的对象的功能。而�
- 原文作者:知识铺
- 原文链接:https://geek.zshipu.com/post/%E4%BA%92%E8%81%94%E7%BD%91/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%BC%96%E7%A8%8B%E4%B9%8B%E7%B1%BB%E5%92%8C%E5%AF%B9%E8%B1%A1/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
- 免责声明:本页面内容均来源于站内编辑发布,部分信息来源互联网,并不意味着本站赞同其观点或者证实其内容的真实性,如涉及版权等问题,请立即联系客服进行更改或删除,保证您的合法权益。转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 sblig@126.com