Scala-类、对象、继承、特质

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=_

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,794评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,050评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,587评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,861评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,901评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,898评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,832评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,617评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,077评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,349评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,483评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,199评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,824评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,442评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,632评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,474评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,393评论 2 352

推荐阅读更多精彩内容

  • Scala与Java的关系 Scala与Java的关系是非常紧密的!! 因为Scala是基于Java虚拟机,也就是...
    灯火gg阅读 3,437评论 1 24
  • 1.1. 什么是Scala Scala是一种多范式的编程语言,其设计的初衷是要集成面向对象编程和函数式编程的各种特...
    文子轩阅读 1,529评论 1 3
  • 今天一早起来,外面宛如仙境,我拍了几张,请看仙境小区: 湖边的樱花沾了小水滴,叶子很美 树枝上有个小蜘蛛,织了网,...
    lemei阅读 175评论 0 2
  • 医院里消毒水的气味,总夹杂着陈旧的情绪 他们说未来要遇到的人,会有各种途径侵袭 打开笔记本的那刻,误打误撞的你突然...
    火锅不暖阅读 736评论 5 7
  • ——————给我最爱最爱的老妹 10年的12月,你诞生在地球上,那时我还在学校,并...
    Switches阅读 292评论 2 1