关闭

[Scala]Scala学习笔记四 类

标签: Scalaclass
374人阅读 评论(0) 收藏 举报
分类:

1. 简单类与无参方法

class Person {
  var age = 0 // 必须初始化字段
  def getAge() = age // 方法默认为公有的
}

备注

在Scala中,类并不声明为public. Scala源文件可以包含多个类,所有这些类都具有公有可见性.属性不声明默认为public.

使用类:

val p = new Person // 或者new Person()
p.age = 23
println(p.getAge()) // 23

调用无参方法时,可以写上圆括号,也可以不写:

p.getAge() // 23
p.getAge   // 23

2. 带getter和setter的属性

2.1 Java getter和setter

在Java类中,我们并不喜欢使用公有字段:

public class Person{
  public int age; // Java中不推荐使用这种方式
}

更倾向于使用getter和setter方法:

public class Person{
  private int age;
  public int getAge() {return age;}
  public void setAge(int age) {this.age = age;}
}

像这样的一对getter/setter通常被称为属性.我们会说Person类有一个age属性.

2.2 Scala getter和setter

在Scala中对每个字段都提供了getter和setter方法:

class Person{
  var age = 0
}

scala生成面向JVM的类,会生成一个私有的age字段以及相应的getter和setter方法.这两个方法都是公有的,因为我们没有将age声明为private.(对于私有字段而言,getter和setter方法也是私有的) 

在scala中getter和setter方法分别叫ageage_=.使用的时候如下:

val p = new Person
p.age = 21 // 调用p.age_=(21)
println(p.age) // 调用p.age()方法

备注

在scala中,getter和setter方法并非被命名为getXXX和setXXX,不过用意相同.

任何时候我们都可以自己重新定义getter和setter方法:

class Person {
  private var privateAge = 0
  def age = privateAge
  def age_= (newAge : Int): Unit = {
    if(newAge > 150){
      privateAge = 150
    }
    else if(newAge < 0){
      privateAge = 0
    }
  }
}

使用:

val p = new Person
p.age = -1;
println(p.age) // 0
p.age = 189
println(p.age) // 150

备注

Scala对每个字段生成getter和setter方法听上去有些恐怖,不过你可以控制这个过程:

  • 如果字段是私有的,则getter和setter方法也是私有的
  • 如果字段是val,则只有getter方法被生成
  • 如果你不需要任何的getter和setter方法,可以将字段声明为private[this]

2.3 Example

(1) 对于公有字段,getter和setter方法是公有的:

class Student {
  var age = 22
}

val stu = new Student
stu.age = 23
println(stu.age) // 23

(2) 对于私有字段,getter和setter方法是私有的:

class Student {
  private var age = 22
}

val stu = new Student
//stu.age = 23 // symbol age is inaccessible from this place
//println(stu.age) // symbol age is inaccessible from this place

(3) 如果字段是val,则只有getter方法被生成:

class Student {
  val age = 22
}

val stu = new Student
// stu.age = 23 // reassignment to val
println(stu.age) // 22

3. 只带getter的属性

如果只想需要一个只读的属性,有getter但没有setter,属性的值在对象构建完成之后就不再改变了,可以使用val字段:

class Student {
  val age = 22
}

Scala会生成一个私有的final字段和一个getter方法,但没有setter方法

4. 对象私有字段

在Scala中,方法可以访问该类的所有对象的私有字段:

class Counter {
  private var value = 0
  def increment(): Unit = {
    value += 1
  }
  // 对象可以访问另一个对象的私有字段
  def isLess (other : Counter) = value < other.value
}

之所以访问other.value是合法的,是因为other也是Counter对象,这与Java的private权限不一样.

Scala允许我们定义更加严格的访问限制,通过private[this]这个修饰符来实现:

private[this] var value = 0

这样other.value是不被允许访问的,这样以来Counter类只能访问当前对象的value字段,而不能访问同样是Counter类型的其他对象的字段.

Scala允许你将访问权限赋予指定得类,private[类名]可以定义仅有指定类的方法可以访问给定的字段.这里的类名必须是当前定义的类,或者是包含该类的外部类.

备注

对于类私有的字段(private),Scala会生成私有的getter和setter方法,但是对于对象私有的字段,不会生成getter和setter方法.

5. Bean属性

Scala对于你定义的字段提供了getter和setter方法,但是并不是Java工具所期望的.JavaBeans规范把Java属性定义为一对getXXX/setXXX方法.很多Java工具都依赖这样的命令习惯.

Scala给我们提供了@BeanProperty注解,这样就会字段生成我们期望的getXXX和setXXX方法:

class Student {
  @BeanProperty
  var age = 22
}

val stu = new Student
stu.setAge(25)
println(stu.getAge()) // 25

总结

scala字段生成的方法何时使用
val/var name公有的name name_=(仅限var)实现一个可以被公开访问并且背后是以字段形式保存的属性
@BeanProperty val/var name公有的name getName() name_=(仅限var) setName() (仅限var)与JavaBeans互操作
private val/var name私有的name name_=(仅限var)用于将字段访问限制在本类的方法.尽量使用private,除非真的需要一个公有属性
private[this] val/var name用于将字段访问限制在同一个对象上调用的方法.不经常用
private[类名] val/var name依赖于具体实现将访问权限赋予外部类.不经常使用

6. 辅助构造器

Scala可以有任意多的构造器,不过,Scala有一个构造器比其他所有构造器都重要,就是主构造器,除了主构造器之外,类还有任意多的辅助构造器.其同Java中的构造器十分相似,只有两处不同:

  • 辅助构造器的名称为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
  }
}

可以使用如下三种方式构造对象:

val p1 = new Person // 调用主构造器
val p2 = new Person("Bob") // 调用第一个辅助构造器
val p3 = new Person("Bob", 25) // 调用第二个辅助构造器

7. 主构造器

在Scala中,每个类都有主构造器.主构造器并不以this方法定义,而是与类定义交织在一起.

(1) 主构造器的参数直接放在类名之后

class Person(val name:String) {
  private var age = 0
  def this (name : String, age : Int){
    this(name) // 调用主构造器
    this.age = age
  }
}

主构造器的参数被编译成字段,其值被初始化成构造时传入的参数.上述示例中name和age为Person类的字段.

(2) 主构造器会执行类定义中的所有语句

class Person(val name:String) {
  println("constructed a person ...")
  private var age = 0

  def this (name : String, age : Int){
    this(name) // 调用主构造器
    this.age = age
  }
}

println语句是主构造器的一部分.每当有对象被构造出来时.上述代码就会被执行

(3) 通常可以在主构造器中使用默认参数来避免使用过多的辅助构造器

class Person(val name:String = "", val age: Int = 0) {
}

备注

如果类名之后没有参数,则该类具备一个无参主构造器.

0
0
查看评论

Scala学习笔记1 - 基础

本文档针对scala 2.10.x,由于scala目前发展迅速,因此可能会和其他版本的不同。 ===概述          scala是一门以java虚拟机(JVM)为目标运行环境并将面向对象和函数式编程的最佳特性结...
  • guohecang
  • guohecang
  • 2016-08-04 11:47
  • 751

SCALA学习笔记(一)

变量 获取变量的值是一个耗时的工作时,可以考虑使用lazy var. lazy val forLater = someTimeConsumingOperation() scala> val first :: rest = List(1, 2, 3) first: Int = 1...
  • bluishglc
  • bluishglc
  • 2015-02-27 08:46
  • 23541

Scala的学习笔记_第一天

以一次接触Scala,记下的部分笔记,内容还会持续的更新,学习.
  • Abandon_Sun
  • Abandon_Sun
  • 2017-07-25 21:41
  • 209

Scala入门到精通——第十节 Scala类层次结构、Traits初步

本节主要内容 Scala类层次结构总览 Scala中原生类型的实现方式解析 Nothing、Null类型解析 Traits简介 Traits几种不同使用方式 1 Scala类层次结构Scala中的类层次结构图如下: 来源:Programming in Scala从上面的类层次结构图中可以看到,处于...
  • lovehuangjiaju
  • lovehuangjiaju
  • 2015-07-25 22:39
  • 13558

Scala开篇-类与成员入门介绍

一、Scala类与成员概念        Scala编程语言,既是面向对象的编程语言,也是面向函数式的编程语言,很完美地融合了两位的优点。在章节介绍的是,在Scala编程使用面向对象的类。在Scala编程中,使用class关键字来定义1个scala类,然后使...
  • Veechange
  • Veechange
  • 2016-12-14 11:40
  • 546

【Scala】Scala的类层级

Scala的类层级Scala里,每个类都继承自通用的名为Any的超类。因为所有的类都是Any的子类,所以定义在Any中的方法就是“共同的”方法:它们可以被任何对象调用。Scala还在层级的底端定义了一些类,如Null和Nothing,扮演通用的子类。即,Any是所有其他类的超类,Nothing是所有...
  • JasonDing1354
  • JasonDing1354
  • 2015-06-15 20:28
  • 1531

Scala类与对象

Scala类与对象       类简介 简介 类是对象的蓝图。一旦你定义了类,就可以用关键字new根据类的蓝图创建对象。在类的定义里,可以放置字段和方法,这些被笼统地称为成员。对于字段,不管是val还是var定义的,都是指向对象的变量。对于方法,用def定义,包含了可执...
  • u011204847
  • u011204847
  • 2016-04-09 15:23
  • 3871

Scala中类的继承,超类的重载等

Scala中类的继承,超类的重载等 (1)与Java语言一样,Scala语言也是使用extends关键字实现子类对父类的继承。  (2)子类中的方法和字段可以使用 override 关键字实现对它的超类(父类)中同名的方法或字段进行覆写(重写)。 (3)当子类使用...
  • kxr0502
  • kxr0502
  • 2015-08-23 22:38
  • 750

Scala样例类详细解释

 case类在模式匹配和actor中经常使用到,当一个类被定义成为case类后,Scala会自动帮你创建一个伴生对象并帮你实现了一系列方法且带来了不少好处,如下: 1.实现了apply方法,意味着你不需要使用new关键字就能创建该类对象 ? 1 ...
  • m0_37972030
  • m0_37972030
  • 2017-08-02 22:09
  • 513

23.scala编程思想笔记——类参数

23.scala编程思想笔记——类参数 欢迎转载,转载请标明出处: 源码下载连接请见第一篇笔记。          在创建新对象时,一般是通过传递某些信息进行初始化,此时可以使用类参数。类参数列表看起来与方法参数列表一样...
  • notbaron
  • notbaron
  • 2016-01-01 20:31
  • 30466
    个人资料
    • 访问:1517573次
    • 积分:22609
    • 等级:
    • 排名:第378名
    • 原创:624篇
    • 转载:133篇
    • 译文:60篇
    • 评论:189条
    博客专栏
    文章分类
    最新评论