[Scala]Scala学习笔记四 类
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方法分别叫age和age_=.使用的时候如下:
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) {
}
备注
如果类名之后没有参数,则该类具备一个无参主构造器.
[Scala]Scala学习笔记四 类的更多相关文章
- Scala入门学习笔记四--List使用
前言 本篇将介绍一个和Array很相似的集合List,更多内容请参考:Scala教程 本篇知识点概括 List的构造 List与Array的区别 List的常用方法 List伴生对象的方法 ::和:: ...
- 初探swift语言的学习笔记四(类对象,函数)
作者:fengsh998 原文地址:http://blog.csdn.net/fengsh998/article/details/29606137 转载请注明出处 假设认为文章对你有所帮助,请通过留言 ...
- Scala入门学习笔记三--数组使用
前言 本篇主要讲Scala的Array.BufferArray.List,更多教程请参考:Scala教程 本篇知识点概括 若长度固定则使用Array,若长度可能有 变化则使用ArrayBuffer 提 ...
- Typescript 学习笔记四:回忆ES5 中的类
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻
前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ...
- IOS学习笔记(四)之UITextField和UITextView控件学习
IOS学习笔记(四)之UITextField和UITextView控件学习(博客地址:http://blog.csdn.net/developer_jiangqq) Author:hmjiangqq ...
- java之jvm学习笔记四(安全管理器)
java之jvm学习笔记四(安全管理器) 前面已经简述了java的安全模型的两个组成部分(类装载器,class文件校验器),接下来学习的是java安全模型的另外一个重要组成部分安全管理器. 安全管理器 ...
- python3.4学习笔记(四) 3.x和2.x的区别,持续更新
python3.4学习笔记(四) 3.x和2.x的区别 在2.x中:print html,3.x中必须改成:print(html) import urllib2ImportError: No modu ...
- Java学习笔记——File类之文件管理和读写操作、下载图片
Java学习笔记——File类之文件管理和读写操作.下载图片 File类的总结: 1.文件和文件夹的创建 2.文件的读取 3.文件的写入 4.文件的复制(字符流.字节流.处理流) 5.以图片地址下载图 ...
随机推荐
- Myeclipse中java项目转换为Web项目
https://blog.csdn.net/u010097777/article/details/51281059 这两天工作安排做一个跳转页面,不过昨天发布自己的Tomact花了不少时间,给的项目添 ...
- SaltStack应用grains和jinja模板-第四篇
目标需求 1.使用jinja模板让apache配置监听本地ip地址 2.了解grains的基本使用方法 说明:实验环境是在前面的第二篇和第三篇基础上完成 实现步骤 使用grains获取ip地址信息 使 ...
- 提高ubuntu系统性能的小技巧
在UBUNTU系统里面,并不是你的物理内存全部耗尽之后,系统才使用swap分区!系统的swappiness设定值,对如何使用swap分区是有着很大的联系,并不是当swappiness=0的时候就不使用 ...
- 数据库还原,System.Data.SqlClient.SqlError: 因为数据库正在使用,所以无法获得对数据库的独占访问权。 (Microsoft.SqlServer.SmoExtended)
数据库还原问题: System.Data.SqlClient.SqlError: 因为数据库正在使用,所以无法获得对数据库的独占访问权. (Microsoft.SqlServer.SmoExtende ...
- Java类继承关系中的初始化顺序
Java类初始化的顺序经常让人犯迷糊,现在本文尝试着从JVM的角度,对Java非继承和继承关系中类的初始化顺序进行试验,尝试给出JVM角度的解释. 非继承关系中的初始化顺序 对于非继承关系,主类Ini ...
- 从Github上轻松安装R包—githubinstall包--转载
1.综述 越来越多的R包正在由世界上不同的人所创建,其中一部分原因是devtools包使得开发R包1变得更加简单.devtools包不仅让开发R包变得简单,而且用于分发R包. 当开发者发布一个R包的时 ...
- Python基础笔记系列八:字符串的运算和相关函数
本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!! 字符串的运算1.字符串的加法和乘法 python中不但支持字符串相加,还支 ...
- LeetCode第[79]题(Java):Word Search(矩阵单词搜索)
题目:矩阵单词搜索 难度:Medium 题目内容: Given a 2D board and a word, find if the word exists in the grid. The word ...
- 如何选择正确的angular2学习曲线?
参考: https://www.zhihu.com/question/50800464/answer/122921043 https://www.zhihu.com/question/48670501 ...
- 设计模式--门面模式C++实现
门面模式C++实现 1定义facade 要求一个子系统的外部接口与其内部的通信必须通过一个统一的接口进行.门面模式提供一个高层次的接口,使得子系统更容易视同 注:门面模式注重统一对象,也就是提供一个访 ...