Scala类和对象详解
一、类定义、创建对象
Scala和Java一样,用class关键字来创建类,eg:
class Student{
var score:Int=0
}
利用javap -private Student命令可以看到上述Scala文件对应的字节码文件内容为:
可以看到,编译后成员变量score前面的限定符为private ,Scala默认生成了score()和score_=()方法,JVM由于不允许出现=,所以用$eq代替了。生成的score()对应Java中的setter方法,score_=()对应Java中的getter方法,生成的字节码文件中setter和getter方法是公有的。因此可以直接用new来创建对象。
val stu = new Student()
t.score_=20 //调用setter方法
t.score=20 //直接修改,但其实也是调用setter方法
t.score //调用getter方法
当然也可以定义自己的setter,getter方法,如下
class Student{
private var privateScore:Int=0
def score=privateScore
def score_=(score:Int){
this.privateScore=score
}
}
对应二进制文件如下:
可以看到定义的私有成员其自带的setter和getter方法被private修饰,而我们自己的定义的setter和getter方法可以被访问
val stu=new Student( )
stu.score //访问自定义的getter方法
stu.score = 30 //直接赋值法,其实调用的是setter方法
stu.score_ = 30 //setter方法
通过stu.score=30的这种方法赋值,调用者无需知道是通过字段访问还是方法调用来操作的,这就是著名的统一访问原则
如果类的成员域是val类型的变量,则只会生成getter方法
class Student {val score:Int=0 }
对应二进制文件如下:
可以看出:val变量对应的Java中final类型的变量,只生成了getter方法,如果将成员域定义为private[this],则不会生成getter、setter方法
class Student {private[this] var score:Int=0 }
对应二进制文件如下:
Java中,定义JavaBean时,生成的是setXxx()和getXxx()方法,但scala生成的getter()和setter()方法并不是这样的,如果程序也需要自动生成getter和setter方法,需要引入scala.reflect.BeanProperty,然后采用注解的方式修饰变量
class Student {@BeanProperty var score:Int=0 }
对应二进制文件如下:
下图是setter、getter方法的产生规则
来源:scala for the impatient
二、类的主构造器
Student.scala文件
class Student(var name:String,var age:Int) //括号里的变量为主构造器的参数
编译后的二进制文件
主构造器会执行类中方法外的所有语句
class Student(var name: String, var age: Int) {//println将作为主构建器中的一部分,在创建对象时被执行 println("被主构造器执行的代码 ........")//重写toString()方法 override def toString: String = name + ":" + agedef ceshi()={print("不输出")} }
二进制文件如下:
主构造器还可以使用默认参数
class Student(val name:String="name",val score:Int=60){println("默认参数主构造器中的代码")val age:Int=10 override def toString: String = name + ":" + age }
二进制文件如下:
主构造器中的参数还可以加访问修饰符
class Student(val name:String="name",private val score:Int=60){println("主构造器中的参数加访问修饰符")val age:Int=10 override def toString: String = name + ":" + age }
二进制文件如下:可以看出private修饰的score,其getter方法是私有的,外部不能访问
当主构造器的参数不用var或val修饰的时候,参数会生成类的私有val成员,并且不会产生getter和setter方法
class Student(name:String,score:Int){println("主构造器中的参数不用var和val修饰")val age:Int=10 override def toString: String = name + ":" + age }
二进制文件如下:
主构造器参数不加var和val相当于如下代码:
class Student(private[this] val name:String,private[this] val score:Int){println("主构造器中的参数不用var和val修饰相当于参数前面加private[this]")val age:Int=10 override def toString: String = name + ":" + age }
二进制文件如下:
下图给出了Scala中主构造器参数生成器类成员和方法时的规则
来源:scala for the impatient
在某些情况下,可能需要禁用主构造器,代码如下:
//类名后面紧跟private关键字可以将主构造器设为私有,不允许外部使用
class Student private(var name:String,var score:Int){println("禁用主构造器中的参数")val age:Int=10 }
二进制代码如下:
从上可以看出,编译后的文件主构造器被private修饰了,外部不能访问
三、辅助构造函数
当禁用了主构造器,就必须使用辅助构造函数来创建对象。辅助构造函数具有以下两个特点:(1)辅助构造器名称为this(2)调用辅助构造函数时,必须先调用主构造函数或其他已经定义好的构造函数。
1、只有辅助构造函数的Student类,注意:在定义辅助构造函数时,需要注意构造函数的顺序,不要将在构造函数中调用之前未定义的辅助构造函数,否则会发声编译错误
class Student {private var name: String = null private var age: Int = 20 private var sex: String = "man" //辅助构造器 def this(name:String){this()this.name=name}def this(name:String,age:Int){this(name)this.age=age}def this(name:String,age:Int,sex:String){this(name,age)this.sex=sex} }
二进制文件如下:
2、带主构造函数、辅助构造函数的类
class Student(name: String,age: Int) {private var sex:String="man" //辅助构造器 def this(name:String,age:Int,sex:String){this(name,age)this.sex=sex}}
二进制文件如下:
之前提到过,有时候可能会禁用掉主构造器函数,此时只能通过辅助构造器函数来创建对象
class Student private(name: String,age: Int) {private var sex:String="man" //辅助构造器 def this(name:String,age:Int,sex:String){this(name,age)this.sex=sex} }
二进制文件如下:
4、单例对象
Scala中,如果我们想像Java中一样直接使用类名来调用方法或成员变量的时候,需要创建单例对象来实现,如下
object Student{private var sex:String="man" def describle()={println("我是单例对象中的成员方法")}def main(args: Array[String]): Unit = {Student.describle()} }
object Student编码后将生成两个字节码文件,Student$.class和Student.class
Student$.class编译后的二进制文件如下:
Student.class编译后的二进制文件如下:
可以看出,object Student最终生成了两个类,分别是Student和Student$,它们都是final类型的,而且Student的构造方法是私有的,通过静态成员域public static final test.Student$ MODULES$对Student进行引用,这其实Java语言中单例实现方式
5、伴生类和伴生对象
在同一个Scala文件中,存在相同名称的object和class,此时object 称为class的伴生对象,而class称为object的伴生类,伴生类和伴生对象本质上是不同的两个类,只不过它们两个之间可以互相访问对方的任何成员变量和方法,包括私有的。
6、apply方法
利用apply方法可以直接利用类名创建对象,比如说创建集合,val list=List("A","B","C"),这其实就是调用
val list=List.apply("A","B","C"),只不过第一种方法更简洁,但需要指出的是,这种创建方式仍然免不了new,它后面仍是new的方式,只不过我们在使用的时候可以省去new关键字
7、应用程序对象
我们都知道,main方法是程序的入口,但scala可以通过继承App来省去定义main方法,此时代码更加简洁,App其实是一种trait,它帮助定义了main方法
8、抽象类
抽象类不能被实例化,其中定义了抽象方法,如果要具体实现需要被非抽象子类继承来实现。除抽象方法外,抽象类中还可以有抽象字段。
Scala类和对象详解相关推荐
- Scala 类和对象详解
Scala 类和对象 类是对象的抽象,而对象是类的具体实例.类是抽象的,不占用内存,而对象是具体的,占用存储空间.类是用于创建对象的蓝图,它是一个定义包括在特定类型的对象中的方法和变量的软件模板. 我 ...
- python类和对象详解_Python公开课 - 详解面向对象
前言 在C语言中,单纯通过结构化的函数也可以实现很好的软件,顺序思路比较好理解:而C++则以面向对象的思维来进行代码组织,通过定义对象.成员变量.成员函数.以封装.继承和多态等方式来更灵活处理业务逻辑 ...
- 【C++学习笔记一】C++类和对象详解
类定义是以关键字class开头,后面跟类的名称.主体是包含在一对花括号中.类定义后必须跟着一个分号或一个声明列表. 类的对象的公共数据成员可以使用直接成员访问运算符.来访问.需要注意的是,私有的成员和 ...
- Android中使用Intent进行窗体切换,并且传值和自定义类的对象详解
在Android中,Intent对象负责各个Activity窗口之间的切换,同时他更担负起数据传输重任. 一般情况下,使用Intent对象进行简单窗口切换的代码如下: Intent i=new Int ...
- Java 类和对象详解(二)——static关键字
文章目录 1.static关键字 为何会引入这个static 变量? final 和 static 的区别 static 修饰方法 1.static关键字 看见static,本能反应,和对象无关 st ...
- 九 Python 类与对象详解,这是软件工程师的分水岭
目录 1 为什么要面向对象编程 2 核心思想 3 初次体验 4 初始化方法 5 类专用的方法 6 继承(有点像生物的基因传递) 7 灵活的Python,属性自由 8 一切皆是对象 9 OOP的设计方法 ...
- 对python3中pathlib库的Path类的使用详解
原文连接 https://www.jb51.net/article/148789.htm 1.调用库 ? 1 from pathlib import 2.创建Path对象 ? 1 2 3 4 5 ...
- 【ES6】Promise对象详解
[ES6]Promise对象详解 一.Promise对象的含义 二.Promise对象的用法 三.Promise对象的几个应用[重点] 1.时间延迟函数 2.图片异步加载 查看更多ES6教学文章: 参 ...
- c++类的构造函数详解
c++构造函数的知识在各种c++教材上已有介绍,不过初学者往往不太注意观察和总结其中各种构造函数的特点和用法,故在此我根据自己的c++编程经验总结了一下c++中各种构造函数的特点,并附上例子,希望对初 ...
最新文章
- JS小数点加减乘除运算后位数增加的解决方案
- gnujaxp.jar与struts2中的xwork核心包冲突
- std:forward 完美转发
- Pl/sql 如何将oracle的表数据导出成excel文件?
- excel 下拉框选择月份显示不同的日历_秒杀Excel的数据分析工具,几分钟教你完成数据填报...
- struts2面试问题_Struts2面试问答
- mysql虚拟列表_「前端进阶」高性能渲染十万条数据(虚拟列表)
- Laravel核心解读 -- 事件系统
- 卸载驱动出现:rmmod: can't change directory to '/lib/modules': No such file or directory
- LeetCode-107二叉树的层次遍历 II-BFS实现
- 曾经的那些绝世电脑高手们
- 记录一个Lock和sychronized应用及双检锁
- INTELIED,PCIIEDX, ATAPI,Disk.sys的关系
- 【工具】-13UML泳道图
- 工作计划表怎么做?30份Excel工作计划表模板,职场人必备,可套用
- ckeditor java 取值_Jquery 对Ckeditor 取值
- JS间隔指定字符数后面插入
- malloc和calloc异同
- Centos7.5部署MySQL5.7基于GTID主从复制+并行复制+半同步复制+读写分离(ProxySQL) 环境- 运维笔记 (完整版)...
- python定义一个字符串变量_python基础入门语法和变量类型(一)