Scala类和对象(二)
1. 类和属性
1.1 如何控制构造函数字段的可见性
在Scala中:
- 如果一个字段被声明为var, Scala会为该字段生成getter和setter方法。
- 如果字段是val, Scala只生成getter方法。
- 如果一个字段没有var或者val的修饰符, Scala比较保守,不会生成getter和setter方法。
- 另外,var和val字段可以被private关键字修饰,这样可以防止生成getter和setter方法。
我们看一下测试代码:
object Demo{
def main(args: Array[String]): Unit = {
val p = new Person("haah")
println(p.name)
}
class Person(var name:String){
}
}
结果:
haah
我们再把name设置为val:
还没有到运行阶段,编译器自动捕获了异常。改为var就可以了。
如果设置为非val和非var的字段:
直接找不到name这个对象,当构造函数参数既没有声明为val或var时,字段的可见性很受限制,井且Scala不会为此生成访问修改方法。
给val或者var加上private,这个关键字会阻止getter和setter方法的生成,所以这种宇段只能被类的成员变量使用。
2. 构造函数
如同在java中可以定义多个构造函数,Scala中也可以,不同的是除了主构造函数以外其余的构造函数都被称为辅助构造函数。所有的辅助构造函数必须以this为名,另外每个构造函数必须调用之前已经定义好了的构造函数:
//主构造函数
class MakePizza(var size:Int,var pizzaType:String){
//辅构造函数
def this(pizzaAuthor:String){
this(size,"3")
}
//辅构造函数
def this(){
this("libai")
}
}
定义私有主构造函数:
class Order private{
}
私有构造函数是无法实例化的。我们知道在java中实现单例模式就是把构造函数私有化。提供一个getInstance方法来初始化类。
class MakePizza private (var size:Int,var pizzaType:String){
object getInstance extends MakePizza(size,pizzaType){
val makePizza = new MakePizza(size,pizzaType)
}
}
设置构造函数参数默认值
class Socket(var timeout:Int = 10000)
那么在调用构造函数的时候就可以不指定默认值:
val s = new Socket
用case类生成模板代码:
定义case类可以生成模板类,包括如下方法:apply,unapply,toString,equals,hashCode。
case class Person(name:String,relation:String)
将类定义为case类会生成许多模板代码,好处在于:
- 会生成一个apply方怯,这样就可以不用new关键字创建新的实例。
- 由于case类的构造函数参数默认是val ,那么构造函数参数会自动生成访问方站。如果是var也会有修改方怯。
- 会生成一个默认的toString方怯。
- 会生成一个unapply方法,在模式匹配时很好用。
- 会生成equals和hashCode方法。
- 还有一个copy方站。
定义case类,就不用再new来创建一个实例:
val wmily = Person("xiaoming","niece")
case类的构造参数默认是val,所以会自动生成get方法,不会生成set。当把case类的构造方法参数设置为var的时候就会有get和set。
case类主要是为了创建“不可变的记录”,这样容易在模式匹配中使用。正因为如此,casel的构造函数参数默认值是val,如果你改为var那就违背了case的本意。
3. 方法
在java中声明一个方法如下:
public String doSomething(int x){
}
在scala中则是这样:
sef doSomeThing(x:Int):String = {
}
控制方法的作用域:
Scala中的方法缺省是public。
在java中protected修饰的方法对同一包中的类都可见。但是在Scala中仅对该类的子类可见。
下表中给出了Scala中各种级别的访问控制:
| 修饰符 | 描述 |
|---|---|
| private[this] | 对当前实例可见 |
| private | 对当前类的所有实例可见 |
| protected | 对当前类以及其子类的实例可见 |
| private[model] | 对model包下的所有类可见 |
| private[coolapp] | 对cooapp包下的所有类可见 |
| private[acme] | 对acme包下的所有类可见 |
| 无修饰符 | 公开方法 |
调用父类中的方法:
Scala中调用父类,用super代表父类,然后是方法名:
class App extends Fruit{
override def onCreate(color:String){
super.onCreate(color)
}
}
可以继承多个类:
与java中不同的是Scala的类对象可以同时继承多个类。如果继承的多个类中有相同的方法可以用如下方式选择要使用哪个类中的方法:
super[类名].方法名
举个例子:
object Demo{
def main(args: Array[String]): Unit = {
var a = new ShowColor
a.printApple("red")
a.printBanana("yellow")
}
}
trait Fruit{
def getColor(color: String): Unit ={
printf("the color is %s \n",color)
}
}
trait Apple extends Fruit{
override def getColor(color: String): Unit = super.getColor(color)
}
trait Banana extends Fruit{
override def getColor(color: String): Unit = super.getColor(color)
}
class ShowColor extends Fruit with Apple with Banana{
def printSuper(color: String) = super.getColor(color: String)
def printApple(color: String) = super[Apple].getColor(color: String)
def printBanana(color: String) = super[Banana].getColor(color: String)
}
结果:
the color is red
the color is yellow
Process finished with exit code 0
方法参数默认值:
如同python一样,Scala可以给方法的参数一个默认值:
def makeCnnection(timeout:Int = 3000,[protocol:String="http"){
println("timeout = %d,protocol=%s".format(timeout,protocol))
}
定义一个返回多个值(tuples)的方法
如果我们希望一个方法能够返回多个值,又不想把这些值字段用一个对象包装,那么可以使用tuples从方法中返回多个值。
tuples是Scala中的数据类型,表示元组的意思。元组是使用()表示的数据结构。后面我们介绍集合列表的时候会详细说。
加入有如下方法返回了包含3个字段的元组:
def getStackInfo = {
return ("RPC","sufface",34)
}
可以使用一个元组来接收:
val result = getsStackInfo
println(b._1,b._2,b._3)
tuple中的值可以通过其位置来访问。
可变参数的方法
在java中可以传入String 类型的可变参数:String … str,在Scala中也提供可变参数的方法:在参数类型后面加一个 “*”,这个参数就变成了可变参数。
def printAll(str:String*){
}
注意:同java一样,当一个方法包含可变参数的时候,那么这个可变参数必须是在所有参数中最后一个位置,否则会报错。
使用_*来匹配一个序列
对于一个序列:Array,List,Seq,Vector,都可以使用_*来匹配里面的每一个对象,从而可以使他可以当做变参传递给一个方法:
def main(args: Array[String]): Unit = {
val fruit = List("apple","banana","pair")
printAll(fruit: _*)
}
def printAll(str:String*): Unit ={
str.foreach(println)
}
解析fruit的每一个对象然后作为参数传递给printAll()方法。
方法的异常声明
使用@throws注解声明可能抛出的异常。这个和java中的使用方式有区别。
@throws(classOf[Exception])
def paly: Unit ={
//code....
}
4. 对象
对象的强制转换:
使用asInstanceOf将一个实例转换为期望的类型。
val recongnizer = cm.lookup("recongnizer").asInstanceOf[Recognizer]
上面的Scala代码等于下面的java代码:
Recognizer recognizer = (Recognizer)cm.lookup("Recognizer");
java中的对象.class的Scala等价类
在java中当你有一个方法里面要求将不同的对象作为参数传进来然后使用不同对象的不同方法,这个时候你可以传入一个参数:class clz。然后利用反射获取不同对象的方法。
在Scala中使用classOf方法来代替java中的.class。
val info = new DataLine.Info(classOf[TargetDataLine],null)
等价于java中的:
info = new DataLine.info(TargetDataLine.class,null)
用object 启动一个应用:
在Scala中启动一个应用有两种方法:
- 定义继承App特质的object;
定义一个object,并实现main方法
object Demo{
def main(args: Array[String]): Unit = {
println(“hello”)
}def printAll(str:String*): Unit ={
str.foreach(println)
}
}
或者:
object Hello extends App{
println("hello")
}
不用new关键字创建对象实例:
有两种办法:
- 为类对象创建伴生类,并在伴生类内定义一个apply方法;
- 将类定义为case类。
用apply方法创建一个伴生类:
class Person{
var name:String = ""
}
object Person{
def apply(name:String): Person = {
var p = new Person
p.name = name
p
}
}
调用方式:
val carry = Person("carry")
在同一个文件中定义Person类和Person对象,在对象中定义apply方法接受期望的参数,这个方法本质上是类的构造函数。
将类声明为case类:
case class Person(var name:String)
val p = Person("carry")
case类起的作用在于他在伴生类中生成了一个apply方法,上文我们已经说过将一个类定义为case类会自动生成很多方法。
5.包管理
Scala的包管理跟Java类似,但更灵活。除了在类文件的开头用package语句外,还可以用花括号,与C++和C#的命名空间很像。
Scala会隐式的导入两个包:
java.lang._
scala._
Scala里的”_”字符类似于java里的”*”。
5.1 花括号风格的包记号法:
package com.rickiyang.zoo{
class Foo{
//todo
}
class food{
//todo
}
}
这种方式允许在一个文件中放多个包。也可以用“花括号”方式定义嵌套的包。
5.2 在导入时重命名类名:
import java.util.{ArrayList => JavaList}
然后再代码中就可以使用别名了。
当你为你的类取了别名后那么原来的名字就不可以使用了。否则会出错。
6. 特质—>java中的接口
上文中我们使用过trait修饰类,trait就是Scala中的特质,相当于java中的接口。正如Java类能够实现多个接口一样, Scala类可以继承多个特质。所以trait的功能要比java接口的功能要强大的多。
做为普通的接口来使用:
方法如果不需要任何参数,在def后面指定方法名即可:
trait BasePlay{
def playBasketBall
def playFootBall
}
需要参数只需要将其罗列出来:
trait BasePlay{
def playBasketBall(count:Int)
def playFootBall(count:Int)
}
当一个类需要继承特质时,要使用extends和with关键字。只继承一个特质时,使用extends:
class BasketBall extends BasketBall{
//todo
}
- 继承一个类和一个或多个特质时,对类使用extends ,对特质使用with。
- 当一个类继承多个特质时,使用extends继承第一个特质,其余的使用with 。
- 除非实现特质的类是一个抽象类,否则它必须实现特质所有的抽象方怯。
- 如果一个类继承了一个特质但是没有实现它的抽象方法,这个类必须被声明为抽象类。
- 特质也可以继承另一个特质。
像抽象类一样使用特质:
定义为trait的类中既可以有抽象方法也可以有已经实现了的方法。
trait BasePlay{
def playBasketBall {println("haha")}
def playFootBall
}
class Football extends BasePlay {
override def playFootBall: Unit = {
println("hahahh football")
}
}
对于trait中已经实现了的方法,他的继承类可以重写也可以不重写。但是抽象方法一定要重写,否则继承类必须定义为抽象类(abstract)。
Scala类和对象(二)的更多相关文章
- Scala实战高手****第9课:Scala类和对象彻底实战和Spark源码鉴赏
scala类和对象 RDD中创建_sc和deps相比java更加的简洁. 在Spark的例如SparkContext.sqlSpark等全局成员在完成实例化. 在唯一实例的时候一般不会去使用伴生对象a ...
- Spark记录-Scala类和对象
本章将介绍如何在Scala编程中使用类和对象.类是对象的蓝图(或叫模板).定义一个类后,可以使用关键字new来创建一个类的对象. 通过对象可以使用定义的类的所有功能. 下面的图通过一个包含成员变量(n ...
- C++中的类和对象(二)
一,对象的动态建立和释放 1.什么是对象的动态建立和释放 通常我们创建的对象都是由C++编译器为我们在栈内存中创建的,我们无法对其进行生命周期的管理.所以我们需要动态的去建立该对象,因此我们需要在堆内 ...
- Scala 类和对象
Scala class: Scala 源文件中可以有很多类(class),这些类默认都是Public的,public是Scala的默认访问级别.在Scala中,声明一个未用priavate修饰的字段 ...
- Scala类与对象
类简介 简介 类是对象的蓝图.一旦你定义了类,就可以用关键字new根据类的蓝图创建对象.在类的定义里,可以放置字段和方法,这些被笼统地称为成员.对于字段,不管是val还是var定义的,都是指向对象的变 ...
- Scala类和对象
1.面向对象 Scala的类与java.C++的一些比起来更简洁,速度更快 对象:使用object关键字修饰的 类:使用class关键字修饰的new Person()实例对象 new类:类的实例(对象 ...
- scala 类,伴生对象
1.属性的定义 编写一个PersonS类,并在其中定义一些属性,通过PersonS.scala 编译后的情况查看,可以知道不同修饰符修饰的属性分别会生成什么方法(set,get) package co ...
- Spark记录-Scala类与对象小例子
//基类-Person class Person(val na: String, val ag: Int) { //属性 var name: String = na var age: Int = ag ...
- php类和对象(二)
面向对象第三大特性:多态 概念: 当父类引用指向子类实例的时候,由于子类对父类函数进行了重写,导致我们在使用该引用取调用相应方法时表现出的不同 条件: 1.必须有继承 2.子类必须对父类的方法进行重写 ...
随机推荐
- 微信支付重复回调,java微信支付回调问题
这几天一直在研究微信支付回调这个问题,发现之前微信支付回调都是正常的也没怎么在意,今天在自己项目上测试的时候发现相同的代码在我这个项目上微信支付回调老是重复执行导致支付成功之后的回调逻辑一直在执行,很 ...
- BZOJ 1061:志愿者招募(单纯型)
题目链接 题意 中文题意. 思路 单纯型模板题. 单纯型用来解决线性规划问题. 留坑待填. 算法思路 好长 模板 论文 卿学姐视频 #include <bits/stdc++.h> usi ...
- oracle group by 显示其他字段
原先用 select key,max(value) from tbl group by key 查询出的结果,但是我要再多加一个TEST字段 根据网友的语句结合起来,以下是可以显示其他字段,并且考虑排 ...
- MySQL sys Schema 简单介绍-2
之前在<MySQL sys Schema 简单介绍-1>中简单的介绍了,sys Schema库中的表.那么这些表都可以查询些什么信息呢?接下来本文将做下介绍. 1. 表的情况 1.1 统计 ...
- MVC模式的介绍(C#)
MVC模式的介绍(C#) Benefits在开发项目中使用“模型-视图-控制器(MVC)”模式的好处在于可以完全消除商业流程和应用表达层之间的相互影响.此外,还可以获得一个完全独立的对象来控制表达 ...
- asp.net core 系列之Configuration
在ASP.NET Core中的App configuration 是通过configuration providers基于key-value对建立的.Configuration providers读取 ...
- 安卓学习资料推荐《深入理解Android:卷2》下载
下载地址:百度云下载地址 编辑推荐 <深入理解Android:卷2>编辑推荐:经典畅销书<深入理解Android:卷I>姊妹篇,51CTO移动开发频道和开源中国社区一致鼎力推荐 ...
- Redis图形化客户端管理软件推荐
Redis是一个超精简的基于内存的键值对NOSQL数据库(key-value),一般对并发有一定要求的应用都用其储存session,乃至整个数据库.不过它公自带一个最小化的命令行式的数据库管理工具re ...
- 宏旺半导体浅谈存储芯片LPDDR4X与UFS2.1的差别
现在市面上手机参数动不动就是8GB+128GB,手机的这些参数是越大越好吗?这些数字代表什么?宏旺半导体ICMAX给大家科普下. 手机的运行内存RAM——LPDDR4X LPDDR4X为RAM(运存) ...
- Java volatile关键字小结
public class Test { public static void main(String[] args){ } } /* 12.3 Java内存模型 Java内存模型定义了线程与主内存之间 ...