Scala入门到精通——第七节:类和对象(二)
本节主要内容
- 单例对象
- 伴生对象与伴生类
- apply方法
- 应用程序对象
- 抽象类
单例对象
在某些应用场景下,我们可能不需要创建对象,而是想直接调用方法,但是Scala语言并不支持静态成员,scala通过单例对象来解决该问题。单例对象的创建方式如下:
object Student {private var studentNo:Int=0;def uniqueStudentNo()={studentNo+=1studentNo}def main(args: Array[String]): Unit = {println(Student.uniqueStudentNo())}
}
object Student编码后将生成两个字节码文件
利用javap命令查看字节码文件内容有:
D:\ScalaWorkspace\ScalaChapter06_2\bin\cn\scala\xtwy>javap -private Student$
警告: 二进制文件Student$包含cn.scala.xtwy.Student$
Compiled from "Student.scala"
public final class cn.scala.xtwy.Student$ {public static final cn.scala.xtwy.Student$ MODULE$;private int studentNo;public static {};private int studentNo();private void studentNo_$eq(int);public int uniqueStudentNo();private cn.scala.xtwy.Student$();
}D:\ScalaWorkspace\ScalaChapter06_2\bin\cn\scala\xtwy>javap -private Student
警告: 二进制文件Student包含cn.scala.xtwy.Student
Compiled from "Student.scala"
public final class cn.scala.xtwy.Student {public static void main(java.lang.String[]);public static int uniqueStudentNo();
}
- 1
不难看出,object Student最终生成了两个类,分别是Student与Student,它们都是final类型的,而且Student的构造方法是私有的,通过静态成员域 public static final cn.scala.xtwy.Student$ MODULE$;
对Student$进行引用,这其实是Java语言中单例实现方式。
单例对象的使用方式同Java语言类引用静态成员是一样的。
伴生对象与伴生类
在前面单例对象的基础之上,我们在object Student所在的文件内定义了一个class Student,此时object Student被称为class Student的伴生对象,而class Student被称为object Student的伴生类:
class Student(var name:String,age:Int)object Student {private var studentNo:Int=0;def uniqueStudentNo()={studentNo+=1studentNo}def main(args: Array[String]): Unit = {println(Student.uniqueStudentNo())}
}//生成的字节码文件如下:
D:\ScalaWorkspace\ScalaChapter06_2\bin\cn\scala\xtwy>javap -private Student
警告: 二进制文件Student包含cn.scala.xtwy.Student
Compiled from "Student.scala"
public class cn.scala.xtwy.Student {private java.lang.String name;private int age;public static void main(java.lang.String[]);public static int uniqueStudentNo();public java.lang.String name();public void name_$eq(java.lang.String);public int age();public void age_$eq(int);public cn.scala.xtwy.Student(java.lang.String, int);
}D:\ScalaWorkspace\ScalaChapter06_2\bin\cn\scala\xtwy>javap -private Student$
警告: 二进制文件Student$包含cn.scala.xtwy.Student$
Compiled from "Student.scala"
public final class cn.scala.xtwy.Student$ {public static final cn.scala.xtwy.Student$ MODULE$;private int studentNo;public static {};private int studentNo();private void studentNo_$eq(int);public int uniqueStudentNo();public void main(java.lang.String[]);private cn.scala.xtwy.Student$();
}
从上面的代码中不难看出,其实伴生对象与伴生类本质上是不同的两个类,只不过伴生类与伴生对象之间可以相互访问到对主的成员包括私有的成员变量或方法,例如:
class Student(var name:String,var age:Int){private var sex:Int=0//直接访问伴生对象的私有成员def printCompanionObject()=println(Student.studentNo)
}object Student {private var studentNo:Int=0;def uniqueStudentNo()={studentNo+=1studentNo}def main(args: Array[String]): Unit = {println(Student.uniqueStudentNo())val s=new Student("john",29)//直接访问伴生类Student中的私有成员println(s.sex)}
}
apply方法
object apply 是一种比较普遍用法。 主要用来解决复杂对象的初始化问题。同时也是单例。
在前几节中我们提到,通过利用apply方法可以直接利用类名创建对象,例如前面在讲集合的时候,可以通过val intList=List(1,2,3)这种方式创建初始化一个列表对象,其实它相当于调用val intList=List.apply(1,2,3),只不过val intList=List(1,2,3)这种创建方式更简洁一点,但我们必须明确的是这种创建方式仍然避免不了new,它后面的实现机制仍然是new的方式,只不过我们自己在使用的时候可以省去new的操作。下面就让我们来自己实现apply方法,代码如下:
//定义Student类,该类称为伴生类,因为在同一个源文件里面,我们还定义了object Student
class Student(var name:String,var age:Int){private var sex:Int=0//直接访问伴生对象的私有成员def printCompanionObject()=println(Student.studentNo)}//伴生对象
object Student {private var studentNo:Int=0;def uniqueStudentNo()={studentNo+=1studentNo}//定义自己的apply方法def apply(name:String,age:Int)=new Student(name,age)def main(args: Array[String]): Unit = {println(Student.uniqueStudentNo())val s=new Student("john",29)//直接访问伴生类Student中的私有成员println(s.sex)//直接利用类名进行对象的创建,这种方式实际上是调用前面的apply方法进行实现,这种方式的好处是避免了自己手动new去创建对象val s1=Student("john",29)println(s1.name)println(s1.age)}
}
应用程序对象
利用IDE开发scala应用程序时,在运行程序时必须指定main方法作为程序的入口,例如:
object Student {//必须定义mian方法作为程序的入口才能执行def main(args: Array[String]): Unit = {val s1=Student("john",29)println(s1.name)println(s1.age)}
}
除了这种方式之外,scala还提供了一种机制,即通过扩展App,在Scala IDE for Eclipse里是通过new->scala app方式创建的
也可在代码直接指定:
//扩展App后,程序可以直接运行,而不需要自己定义main方法,代码更简洁
object AppDemo extends App {println("App Demo")
}
- 1
App其实是一种trait,它帮助我们定义了main方法。
抽象类
抽象类是一种不能被实例化的类,抽象类中包括了若干不能完整定义的方法,这些方法由子类去扩展定义自己的实现。
//scala中的抽象类定义
abstract class Animal {def eat:Unit
}//对应字节码文件
D:\ScalaWorkspace\ScalaChapter06_2\bin\cn\scala\xtwy>javap -private Animal.classCompiled from "human.scala"
public abstract class cn.scala.xtwy.Animal {public abstract void eat();public cn.scala.xtwy.Animal();
}
- 1
除抽象方法外,抽象类中还可以有抽象字段:
abstract class Animal {//抽象字段(域)//前面我们提到,一般类中定义字段的话必须初始化,而抽象类中则没有这要求var height:Int//抽象方法def eat:Unit
}//Person继承Animal,对eat方法进行了实现
//通过主构造器对height参数进行了初始化
class Person(var height:Int) extends Animal{//对父类中的方法进行实现,注意这里面可以不加override关键字def eat()={println("eat by mouth")}}//通过扩展App创建程序的入口
object Person extends App{new Person(10).eat()
}
- 12
//上面这几个类会产生以下四个字节码文件D:\ScalaWorkspace\ScalaChapter06_2\bin\cn\scala\xtwy 的目录2015/07/22 23:28 <DIR> .
2015/07/22 23:28 <DIR> ..
2015/07/22 23:28 675 Animal.class
2015/07/22 23:28 2,143 Person$.class
2015/07/22 23:28 699 Person$delayedInit$body.class
2015/07/22 23:28 1,741 Person.class//字节码内容如下:
//Animal类对应的字节码,可以看到,字节码中包括了抽象字段height的getter和setter方法,只不过它们都是抽象的
D:\ScalaWorkspace\ScalaChapter06_2\bin\cn\scala\xtwy>javap -private Animal.classCompiled from "Person.scala"
public abstract class cn.scala.xtwy.Animal {public abstract int height();public abstract void height_$eq(int);public abstract void eat();public cn.scala.xtwy.Animal();
}//Person类对应的字节码文件
D:\ScalaWorkspace\ScalaChapter06_2\bin\cn\scala\xtwy>javap -private Person.classCompiled from "Person.scala"
public class cn.scala.xtwy.Person extends cn.scala.xtwy.Animal {private int height;public static void main(java.lang.String[]);public static void delayedInit(scala.Function0<scala.runtime.BoxedUnit>);public static java.lang.String[] args();public static void scala$App$_setter_$executionStart_$eq(long);public static long executionStart();public int height();public void height_$eq(int);public void eat();public cn.scala.xtwy.Person(int);
}//伴生对象Person对应的字节码文件内容
D:\ScalaWorkspace\ScalaChapter06_2\bin\cn\scala\xtwy>javap -private Person$.clas
s
Compiled from "Person.scala"
public final class cn.scala.xtwy.Person$ implements scala.App {public static final cn.scala.xtwy.Person$ MODULE$;private final long executionStart;private java.lang.String[] scala$App$$_args;private final scala.collection.mutable.ListBuffer<scala.Function0<scala.runtim
e.BoxedUnit>> scala$App$$initCode;public static {};public long executionStart();public java.lang.String[] scala$App$$_args();public void scala$App$$_args_$eq(java.lang.String[]);public scala.collection.mutable.ListBuffer<scala.Function0<scala.runtime.Boxed
Unit>> scala$App$$initCode();public void scala$App$_setter_$executionStart_$eq(long);public void scala$App$_setter_$scala$App$$initCode_$eq(scala.collection.mutabl
e.ListBuffer);public java.lang.String[] args();public void delayedInit(scala.Function0<scala.runtime.BoxedUnit>);public void main(java.lang.String[]);private cn.scala.xtwy.Person$();
}
Scala入门到精通——第七节:类和对象(二)相关推荐
- Scala入门到精通——第六节:类和对象(一)
本节主要内容 1 类定义.创建对象 2 主构造器 3 辅助构造器 类定义.创建对象 //采用关键字class定义 class Person {//类成员必须初始化,否则会报错//这里定义的是一个公有成 ...
- Scala入门到精通——第二十七节 Scala操纵XML
本节主要内容 XML 字面量 XML内容提取 XML对象序列化及反序列化 XML文件读取与保存 XML模式匹配 1. XML 字面量 XML是一种非常重要的半结构化数据表示方式,目前大量的应用依赖于X ...
- Scala入门到精通——第十七节 类型参数(一)
本节主要内容 类型变量界定(Type Variable Bound) 视图界定(View Bound) 上界(Upper Bound)与下界(Lower Bound) 1. 类型变量界定(Type V ...
- Java入门 第七节 类和对象
文章目录 1. 引言 1.1 什么是对象 1.2. 什么是类 2. 类和对象的关系 2.1 计算机怎么描述世界 2.2 类和对象 语法结构 2.3 创建类 和 调用对象 2.4 简单分析对象创建过程 ...
- Scala入门到精通——第十节 Scala类层次结构、Traits初步
本节主要内容 Scala类层次结构总览 Scala中原生类型的实现方式解析 Nothing.Null类型解析 Traits简介 Traits几种不同使用方式 1 Scala类层次结构 Scala中的类 ...
- Scala入门到精通——第二十一节 类型参数(三)-协变与逆变
本节主要内容 协变 逆变 类型通匹符 1. 协变 协变定义形式如:trait List[+T] {} .当类型S是类型A的子类型时,则List[S]也可以认为是List[A}的子类型,即List[S] ...
- Scala入门到精通——第二十节 类型参数(二)
本节主要内容 Ordering与Ordered特质 上下文界定(Context Bound) 多重界定 类型约束 1. Ordering与Ordered特质 在介绍上下文界定之前,我们对Scala中的 ...
- Scala入门到精通——第十一节 Trait进阶
本节主要内容 trait构造顺序 trait与类的比较 提前定义与懒加载 trait扩展类 self type 1 trait构造顺序 在前一讲当中我们提到,对于不存在具体实现及字段的trait,它最 ...
- Scala入门到精通——第四节 Set、Map、Tuple、队列操作实战
本节主要内容 mutable.immutable集合 Set操作实战 Map操作实战 Tuple操作实战 队列操作实战 栈操作实战 mutable.immutable集合 以下内容来源于Scala官方 ...
最新文章
- JavaWeb 项目安全问题及其解决方案
- 《领域模型》——通过重构得到更深层次的理解
- Why is OFDMA a Magical Feature in the 802.11ax Standard?
- Oracle的NVL函数
- Spring Boot 注解大全,一键收藏了!
- swift 导出测试包(Save for Ad Hoc Deployment)卡在compile bitcode处问题
- linux accept过程,Linux协议栈accept和syn队列问题
- scrapy配合selenium爬取需要反复操作同一个动态页面的方法,解决点击“下一页”但是URL相同的网站
- 设计模式之行为模式(1)-状态、策略、责任链、访问者
- 关于局部变量的几个难点
- Atitit 常用比较复杂的图像滤镜 attilax大总结
- qq空间登录参数详细分析及密码加密最新版
- html计时加速,HTML-加速、再加速(下)_html
- 站在商业、技术与人文三叉路口的实体书店
- 厉害了软考!让你拥有万能的北京“绿卡”居住证!
- SQL注入攻击讲解及PHP防止SQL注入攻击的几种方法
- java rsi_高频交易算法研发心得--RSI指标及应用
- 开源商城系统真的靠谱吗?它有哪些优缺点
- 使用计算机写作与手工写作的异同,会计模拟论文,关于中等职业学校会计模拟实训课程存在相关参考文献资料-免费论文范文...
- 小白学习Java第二十六天
热门文章
- 18行代码AC_排序 HDU - 1106(sstream简单解法)
- MySQL之日期时间处理函数_MySQL之日期时间处理函数
- wmm开启和关闭的区别_【解读】排烟风机应由哪些排烟防火阀连锁关闭
- paradox 修改字段长度_400字的作文就只能写400字?刘强东:这不是笑话
- java getjsonarray_无法在Java中访问getJSONArray
- matlab求固有频率,eig()函数求固有频率和有限元软件求固有频率结果不相等
- 分块的单点修改查询区间和_模版 单点修改,区间查询
- 人工智能tensorflow图的可视化
- Django模板语法
- 关于jboss在jdk6下webservice不正常问题的解决