scala006_面向对象编程类

1课程大纲

scala既能面向对象、又能面向过程; 函数是一级成员
面向对象(封装、继承、多态)
1、定义一个简单地嘞
2、field的getter与setter详解
3、constructor详解,类的构造函数
4、内部类介绍

1 定义一个简单的类

1.1 定义类,包含field以及方法

函数没有参数,可以不用加加括号,不加括号()之后,在外部调用该函数的时候不用加括号。
在类外面的def叫函数
在类里面的def叫方法

scala> :paste
// Entering paste mode (ctrl-D to finish)

class HelloWorld{
 private var name = "leo"
 def sayHello(){print("Hello, "+ name)}
 def getName = name
}

// Exiting paste mode, now interpreting.

defined class HelloWorld

scala>

1.2 创建类的对象,并调用方法

scala> val helloworld = new HelloWorld
helloworld: HelloWorld = HelloWorld@2d745993

scala> helloworld.sayHello()
Hello, leo
scala> helloworld.get
getClass   getName

scala> helloworld.getName
res41: String = leo

# 如果定义方法时不带括号,则调用方法时也不能带括号
scala> helloworld.getName()
<console>:15: error: not enough arguments for method apply: (index: Int)Char in class StringOps.
Unspecified value parameter index.
       helloworld.getName()
                         ^

scala>

1.3 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]

scala> class Student{
     | var name = "leo"
     | }
defined class Student

调用getter和setter方法,分别叫做name和name_ =

scala> val s = new Student
s: Student = Student@5d7911d5
#使用getter方法
scala> s.name
res5: String = leo
#使用setter方法
scala> s.name = "jack"
s.name: String = jack

scala> s.name
res6: String = jack

1.4 自定义getter与setter

如果只是希望拥有简单的getter和setter方法,那么就按照scala提供的语法规则,根据需求为field选择合适的修饰符就好:var、val、private、private[this]
但是如果希望能够自己对getter与setter进行控制,则可以自定义getter与sette方法
自定义setter方法的时候一定要注意scala的语法限制,签名、=、参数间不能有空格

主构造函数没有要求传入参数的时候,声明类的时候可以省略括号。

scala> :paste
// Entering paste mode (ctrl-D to finish)

class Student{
 private var myName = "leo"
 def name = "your name is " + myName
 def name_=(newVlaue : String){
  print("your cannot edit your name!!!")
 }
}

// Exiting paste mode, now interpreting.

defined class Student

scala> val s = new Student
s: Student = Student@73e1ecd0

scala> val s = new Student
s: Student = Student@4b93dd6a

scala> val s = new Student()
s: Student = Student@9d3d54e

scala> s.name
res7: String = your name is leo

scala> s.name = "leo001"
your cannot edit your name!!!s.name: String = your name is leo

scala> s.name
res8: String = your name is leo

1.5 仅暴露field的getter方法

如果你不希望field有setter方法,则可以定义为val,但是此时就再也不能更改field的值了
但是如果希望能够仅仅暴露出一个getter方法,并且还能通过某些方法更改field的值,name需要综合使用private以及自定义getter方法
此时,由于field是private的,所以setter和getter都是private,对外界没有暴露;自己可以实现修改filed值的方法;自己可以覆盖getter方法。

scala> :paste
// Entering paste mode (ctrl-D to finish)

class Student{
 private var myname = "leo"
 def updatename(newname : String){
  if(newname == "leo1") myname = newname
  else print("not accept this new name!!!")
 }
 def name = "your name is " + myname
}

// Exiting paste mode, now interpreting.

defined class Student

scala>

scala> val s = new Student
s: Student = Student@63124022

scala> s.name
res9: String = your name is leo

scala> s.updatename("leo002")
not accept this new name!!!
scala> s.name
res11: String = your name is leo

scala> s.updatename("leo1")

scala> s.name
res13: String = your name is leo1

scala>

1.6 private[this]的使用

如果将field使用private来修饰,那么代表这个field是类私有的,在类的方法中,可以直接访问类的其他对象的private field
这种情况下,如果不希望field被其他对象访问到,那么可以使用private[this],意味着对象私有的field,只能本对象内可以访问到

scala> :paste
// Entering paste mode (ctrl-D to finish)

class Student{
 private var myAge = 0
 def age_=(newAge : Int){
  if(newAge > 0)myAge = newAge
  else print("illeagal age!!!")
 }
 def age = myAge
 def older(s:Student) = {
  myAge > s.myAge
 }
}

// Exiting paste mode, now interpreting.

defined class Student

scala> val s1 = new Student
s1: Student = Student@359e27d2

scala> s1.age = 20
s1.age: Int = 20

scala> val s2 = new Student
s2: Student = Student@574ebdaf

scala> s2.age =25
s2.age: Int = 25

scala> s1.older(s2)
res19: Boolean = false

用 private[this] 声明变量之后,同类之间访问报如下错误:

scala> :paste
// Entering paste mode (ctrl-D to finish)

class Student{
 private[this] var myAge = 0
 def age_=(newValue : Int){
  if(newValue > 0) myAge = newValue
  else print("illegal age!")
 }
 def age = myAge
 def older(s:Student) = {
  myAge > s.myAge
 }
}

// Exiting paste mode, now interpreting.

<console>:26: error: value myAge is not a member of Student
         myAge > s.myAge
                   ^

scala>

1.7 Java风格的getter和setter方法

scala的getter和setter方法的命名与java是不同的,是field和field_=的方式
如果要让scala自动生成java风格的getter和setter方法,只要给field添加@BeanProperty注解即可。
此时会生成3个方法,name:String、name_=(newValue : String):Unit、getName():String、setName(newVaule:String)

scala> import scala.beans.BeanProperty
import scala.beans.BeanProperty

scala> :paste
// Entering paste mode (ctrl-D to finish)

class Student{
 @BeanProperty var name:String = _
}

// Exiting paste mode, now interpreting.

defined class Student

scala> val s = new Student
s: Student = Student@31533eb1

scala> s.getName()
res20: String = null

scala> s.setName("Leo")

scala> s.getName()
res22: String = Leo

scala>
scala> class Student(@BeanProperty var name:String)
defined class Student

scala> val s = new Student("leo")
s: Student = Student@1926f962

scala> s.getName()
res23: String = leo

scala> s.setName("JACK")

scala> s.getName()
res25: String = JACK

scala>

1.8 辅助constructor

构造函数是初始化实例的,scala中包含主构造函数和辅助构造函数
辅助constructor都是用this这个名称的
第一行如果不互相调用,用this()调用主的constructor
不同辅助constructor传入参数必须不同
scala中,可以给类定义多个辅助constructor,类似于java中的构造函数重载
辅助constructor之间可以互相调用,而且必须第一行调用主constructor

scala> :paste
// Entering paste mode (ctrl-D to finish)

class Student{
 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
 }
}

// Exiting paste mode, now interpreting.

defined class Student

scala> val s = new Student
s: Student = Student@4cd8db31

scala> val s2 = new Student("name")
s2: Student = Student@e895e3e

scala> val s3 = new Student("leo",30)
s3: Student = Student@3df3410a

scala>

1.9 主constructor

scala中,主constructor是与类名放在一起的,与java不同
而且类中,没有定义在任何方法或者是代码块之中的代码,就是主constructor的代码,这点感觉没有javaname清晰
在scala中主构造函数是和类名在一起的。

scala> class Student(val name :String,val age:Int){
     | println("your name is " + name +" ,your age is " + age)
     | }
defined class Student

scala> val s = new Student("leo",30)
your name is leo ,your age is 30
s: Student = Student@4d75c604

scala>

主constructor中还可以通过使用默认参数,来给参数默认的值

scala> class Student(val name :String="leo",val age:Int=30){
     | println("your name is " + name +" ,your age is " + age)
     | }
defined class Student

scala> val s = new Student
your name is leo ,your age is 30
s: Student = Student@114b2414

scala>

如果主constructor传入的参数什么修饰都没有,比如name:String,name如果类内部的方法使用到了,则会声明为private[this] name;否则没有该field,就只能被constructor代码使用而已。

scala> class Student(name:String,age:Int){
     | print("-----"+name+"----"+age)
     | }
defined class Student

scala> val s = new Student("leo",20)
-----leo----20s: Student = Student@4b7dc788

1.9 内部类

scala中,同样可以在类中定义内部类;但是与java不同的是,每个外部类的对象的内部类,都是不同的类。

scala> :paste
// Entering paste mode (ctrl-D to finish)

class Class{
 class Student(val name:String){}
 val students = new ArrayBuffer[Student]
 def getStudent(name:String) = {
  new Student(name)
 }
}

// Exiting paste mode, now interpreting.

defined class Class

scala> val c1 = new Class()
c1: Class = Class@5649ec46

scala> val s = cl.getStudent("leo")
<console>:12: error: not found: value cl
       val s = cl.getStudent("leo")
               ^

scala> val s = c1.getStudent("leo")
s: c1.Student = Class$Student@51745f40

scala> c1.students += s
res3: c1.students.type = ArrayBuffer(Class$Student@51745f40)

scala> val c2 = new Class
c2: Class = Class@3c69362a

scala> val s2 = c2.getStudent("jack")
s2: c2.Student = Class$Student@10c07b8d

scala> c1.students += s2
<console>:18: error: type mismatch;
 found   : c2.Student
 required: c1.Student
       c1.students += s2
                      ^
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值