Scala-类、对象、继承、特质
2019-04-13 本文已影响0人
printf200
1、类
1、类的定义和访问限制符
/**
* 类的定义,变量声明与访问限制
* 在Scala中,类并不用声明为public。
*Scala源文件中可以包含多个类,所有这些类都具有公有可见性。
* Created by 12706 on 2017/11/27.
*/
//private[scu]:包可见性scu是包名,除了该包和子包其他包不可见
//Person private表示构造器(无参的主构造器)私有化了,除了伴生对象外其他对象里面一旦创建运行会出错
private[scu] class Person private {
//val修饰的属性,外部只能访问该属性而不能修改(反编译后能看到只有get方法而没有set方法)
val id = 110
//var 修饰的属性,既有get方法也有set方法
var name = "小明"
//private修饰的属性(类私有字段)只能在当前类(以及伴生对象 object Person)中访问
private val age : Int = 18
//对象私有字段,访问权限更加严格的,连伴生对象都不能访问,只能当前类才行
private[this] val height : Int = 16
//getHeight()当然也行
private def getHeight = {
height
}
}
//伴生对象,类和伴生对象之间可以相互访问私有的方法和属性
object Person {
def main(args: Array[String]): Unit = {
//创建对象,当然用new Person()也行
val p = new Person
//访问对象属性,访问不到height属性
println("id:" + p.id)
println("姓名:" + p.name)
println("年龄:" + p.age)
//通过方法获height属性
val height = p.getHeight;
println("身高:" + height)
//修改属性,只能修改到name
p.name = "小雨"
println("姓名:" + p.name)
}
}
class Man {}
object Man {
def main(args: Array[String]): Unit = {
// 运行会出错,因为构造器被私有化了
// val p = new Person
}
}
对上面的demo进行反编译,java代码一目了然
public class Person
{
private final int id = 110;
private String name = "小明";
private final int main$java$cn$scu$scala$day02$Person$$age = 18;
private final int height = 16;
public static void main(String[] paramArrayOfString)
{
Person..MODULE$.main(paramArrayOfString);
}
public int id()
{
return this.id;
}
public String name() { return this.name; }
public void name_$eq(String x$1) { this.name = x$1; }
public int main$java$cn$scu$scala$day02$Person$$age() {
return this.main$java$cn$scu$scala$day02$Person$$age;
}
public int main$java$cn$scu$scala$day02$Person$$getHeight()
{
return this.height;
}
}
2、构造器
/**
* 每个类都有主构造器,主构造器的参数直接放置类名后面,与类交织在一起
* Created by 12706 on 2017/11/27.
*/
//height : Int 相当于private[this] height : int
//反编译的时候能看到成员变量有id,name,age
class People(val id : Int, var name : String, height : Int, private var age : Int = 18) {
}
object People {
def main(args: Array[String]): Unit = {
//age有初始值所以创建对象时可以不指定
val p = new People(1,"小明",60);
//访问不了height属性,height为对象私有字段
println(p.id + " " +p.age + " " +p.name)
val p2 = new People(1,"小明",60,28);
println(p2.id + " " +p2.age + " " +p2.name)
}
}
输出
1 18 小明
1 28 小明
/**
* 辅助构造器的定义
* Created by 12706 on 2017/11/27.
*/
class Student(val id : Int, val name : String) {
println("执行主构造器!")
//用this关键字定义辅助构造器
def this(id : Int, name : String, age : Int){
//每个辅助构造器必须以主构造器或其他的辅助构造器的调用开始
this(id,name)
println("执行辅助构造器")
}
}
object Student {
def main(args: Array[String]): Unit = {
val stu = new Student(1,"小明",20)
//同样还是访问不到age的
println(stu.name)
}
}
/**
* 主构造器会执行类定义中的所有语句
* Created by 12706 on 2017/11/27.
*/
class Prop {
println("执行主构造器")
//定义方法
def method(): Unit ={
println("用我来读取文件内容 !")
}
//读取外部文件内容
try {
//读取的整个文件后转为String
val context = Source.fromFile("d://words.txt").mkString
println(context)
}catch {
case e :Exception => e.printStackTrace()
}finally {
println("读取文件完毕")
}
}
object Prop {
def main(args: Array[String]): Unit = {
val prop = new Prop
println("================")
prop.method
}
}
输出
执行主构造器
hello tom
hello jerry
hello tom
hello jerry
hello tom
hello tom
读取文件完毕
================
用我来读取文件内容 !
2、对象
1、单例对象
在Scala中没有静态方法和静态字段,但是可以使用object这个语法结构来达到同样的目的
1.存放工具方法和常量
2.高效共享单个不可变的实例
3.单例模式
/**
* java中SessionFactory(hibernate或者是mybatis(SqlSessionFactory))的设计就是
* 单例的,通过它来获取Session对象。使用scala来进行简单模拟
* Created by 12706 on 2017/11/27.
*/
//下面相当于java的静态块
object SessionFactory{
var counts = 5;
val buffer = new ArrayBuffer[Session](5)
while (counts>0) {
//给buffer缓存塞入5个Sessio对象
val session = new Session
buffer += session
counts -= 1
}
//获取session对象,相当于java的静态方法
def getSession(): Unit ={
//缓存中取session
buffer.remove(0)
}
def main(args: Array[String]): Unit = {
//单例对象,不需要new,用【类名.方法】调用对象中的方法
val session = SessionFactory.getSession
println(session)
}
}
class Session {
}
2、伴生对象
在Scala的类中,与类名相同的对象叫做伴生对象,类和伴生对象之间可以相互访问私有的方法和属性
/**
* 伴生对象与类之间私有属性的访问
* Created by 12706 on 2017/11/27.
*/
class Dog {
private val name : String = "旺财"
def bark(){
//访问伴生对象的私有属性
println(Dog.voice)
}
}
object Dog {
private val voice : String = "wangwang"
def main(args: Array[String]): Unit = {
val dog = new Dog
//访问对象的私有name属性
println(dog.name)
dog.bark()
}
}
2、apply方法
/**
* apply方法:通常我们会在类的伴生对象中定义apply方法,
* 当遇到类名(参数1,...参数n)时apply方法会被调用
* Created by 12706 on 2017/11/27.
*/
class Point {
private var x : Int = 2
println("主构造器被调用")
def this(x : Int){
this()
this.x = x
}
}
object Point {
def apply(): Unit ={
println("apply()方法被调用")
}
def apply(x : Int, y : Int): Unit = {
println("apply(x : Int, y : Int)方法被调用")
}
def apply(x : Int): Point = {
println("apply(x : Int)方法被调用")
new Point(x)
}
def main(args: Array[String]): Unit = {
val p1 = new Point
println("===================")
//注意两者区别,调用apply方法的时候不会执行主构造器方法
val p2 = Point()
val p3 = Point(3,4)
println("===================")
val p4 = Point(3)
println(p4.x)
}
}
输出
主构造器被调用
===================
apply()方法被调用
apply(x : Int, y : Int)方法被调用
===================
apply(x : Int)方法被调用
主构造器被调用
3
4、应用程序对象
Scala程序都必须从一个对象的main方法开始,可以通过扩展App特质,不写main方法。
/**
* 应用程序对象,单例对象(或者伴生对象)继承App即可,App中定义了main方法被继承过来了
* 所以AppDemo中不需要写main方法了
* Created by 12706 on 2017/11/27.
*/
object AppDemo extends App{
val arr = Array(1,2,3,4)
println(arr.toBuffer)
}
3、继承
1、拓展类
在Scala中扩展类的方式和Java一样都是使用extends关键字,但是并没有使用implements来实现接口,都是用extends。如果继承一个类的同时也实现了很多接口,那么用extends 父类 with 接口1 with 接口2 with…
2、方法的重写
方法重写就是子类中对父类的方法实现重写。
java中接口中都是抽象方法,但是scala中可以有实现,而且关键字是trait称为特质。但是重写一个非抽象方法必须使用override关键字。
3、类型检查和转换
obj.isInstanceOf[C](scala中) ,obj instanceof C(java中)。obj是不是C类型
obj.asInstanceOf[C](scala中),(C)obj(java中),obj类型强转为C类型。
classOf[C](scala中),C.class。获取C类型
/**
* Men是Human类(继承类),同时拥有动物的行为(实现接口)
* Created by 12706 on 2017/11/27.
*/
//Human是类必须接在extends后面
class Men extends Human with Animall{
def say(): Unit = {
println("大家好,我的名字叫:" + name)
}
//重写父类已经实现的方法需要加override关键字,父类没实现那么可加可不加
override def getName(): String = {
this.name
}
}
object Men {
def main(args: Array[String]): Unit = {
val man = new Men
man.name = "xiaoming"
man.say()
println(man.getName())
//类型检查
val b = man.isInstanceOf[Animall]
println(b)
}
}
abstract class Human {
var name : String = _
def say()
}
trait Animall {
def getName(): String = {
"monkey"
}
}
输出
大家好,我的名字叫:xiaoming
xiaoming
true
_ 对变量进行默认初始化,比如var i:Int=_