Scala-類(lèi)、對(duì)象、繼承、特質(zhì)

1、類(lèi)
1、類(lèi)的定義和訪(fǎng)問(wèn)限制符

/**
  * 類(lèi)的定義,變量聲明與訪(fǎng)問(wèn)限制
  * 在Scala中,類(lèi)并不用聲明為public。
  *Scala源文件中可以包含多個(gè)類(lèi),所有這些類(lèi)都具有公有可見(jiàn)性。
  * Created by 12706 on 2017/11/27.
  */
//private[scu]:包可見(jiàn)性scu是包名,除了該包和子包其他包不可見(jiàn)
//Person private表示構(gòu)造器(無(wú)參的主構(gòu)造器)私有化了,除了伴生對(duì)象外其他對(duì)象里面一旦創(chuàng)建運(yùn)行會(huì)出錯(cuò)
private[scu] class Person private {

  //val修飾的屬性,外部只能訪(fǎng)問(wèn)該屬性而不能修改(反編譯后能看到只有g(shù)et方法而沒(méi)有set方法)
  val id = 110
  //var 修飾的屬性,既有g(shù)et方法也有set方法
  var name = "小明"

  //private修飾的屬性(類(lèi)私有字段)只能在當(dāng)前類(lèi)(以及伴生對(duì)象 object Person)中訪(fǎng)問(wèn)
  private val age : Int = 18

  //對(duì)象私有字段,訪(fǎng)問(wèn)權(quán)限更加嚴(yán)格的,連伴生對(duì)象都不能訪(fǎng)問(wèn),只能當(dāng)前類(lèi)才行
  private[this] val height : Int = 16

  //getHeight()當(dāng)然也行
  private def getHeight = {
    height
  }

}

//伴生對(duì)象,類(lèi)和伴生對(duì)象之間可以相互訪(fǎng)問(wèn)私有的方法和屬性
object Person {

  def main(args: Array[String]): Unit = {
    //創(chuàng)建對(duì)象,當(dāng)然用new Person()也行
    val p = new Person

    //訪(fǎng)問(wèn)對(duì)象屬性,訪(fǎng)問(wèn)不到height屬性
    println("id:" + p.id)
    println("姓名:" + p.name)
    println("年齡:" + p.age)
    //通過(guò)方法獲height屬性
    val height = p.getHeight;
    println("身高:" + height)

    //修改屬性,只能修改到name
    p.name = "小雨"
    println("姓名:" + p.name)

  }

}

class Man {}
object Man {
  def main(args: Array[String]): Unit = {
//    運(yùn)行會(huì)出錯(cuò),因?yàn)闃?gòu)造器被私有化了
//   val p = new Person
  }
}

對(duì)上面的demo進(jìn)行反編譯,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、構(gòu)造器

/**
  * 每個(gè)類(lèi)都有主構(gòu)造器,主構(gòu)造器的參數(shù)直接放置類(lèi)名后面,與類(lèi)交織在一起
  * Created by 12706 on 2017/11/27.
  */
//height : Int 相當(dāng)于private[this] height : int
//反編譯的時(shí)候能看到成員變量有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有初始值所以創(chuàng)建對(duì)象時(shí)可以不指定
    val p = new People(1,"小明",60);
    //訪(fǎng)問(wèn)不了height屬性,height為對(duì)象私有字段
    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 小明
/**
  * 輔助構(gòu)造器的定義
  * Created by 12706 on 2017/11/27.
  */
class Student(val id : Int, val name : String) {

  println("執(zhí)行主構(gòu)造器!")

  //用this關(guān)鍵字定義輔助構(gòu)造器
  def this(id : Int, name : String, age : Int){
    //每個(gè)輔助構(gòu)造器必須以主構(gòu)造器或其他的輔助構(gòu)造器的調(diào)用開(kāi)始
    this(id,name)
    println("執(zhí)行輔助構(gòu)造器")
  }
}
object Student {
  def main(args: Array[String]): Unit = {
    val stu = new Student(1,"小明",20)
    //同樣還是訪(fǎng)問(wèn)不到age的
    println(stu.name)
  }
}
/**
  * 主構(gòu)造器會(huì)執(zhí)行類(lèi)定義中的所有語(yǔ)句
  * Created by 12706 on 2017/11/27.
  */
class Prop {

  println("執(zhí)行主構(gòu)造器")

  //定義方法
  def method(): Unit ={
    println("用我來(lái)讀取文件內(nèi)容 !")
  }

  //讀取外部文件內(nèi)容
  try {
    //讀取的整個(gè)文件后轉(zhuǎn)為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
  }
}
輸出
執(zhí)行主構(gòu)造器
hello tom
hello jerry
hello tom
hello jerry
hello tom
hello tom
讀取文件完畢
================
用我來(lái)讀取文件內(nèi)容 !

2、對(duì)象
1、單例對(duì)象
在Scala中沒(méi)有靜態(tài)方法和靜態(tài)字段,但是可以使用object這個(gè)語(yǔ)法結(jié)構(gòu)來(lái)達(dá)到同樣的目的
1.存放工具方法和常量
2.高效共享單個(gè)不可變的實(shí)例
3.單例模式

/**
  * java中SessionFactory(hibernate或者是mybatis(SqlSessionFactory))的設(shè)計(jì)就是
  * 單例的,通過(guò)它來(lái)獲取Session對(duì)象。使用scala來(lái)進(jìn)行簡(jiǎn)單模擬
  * Created by 12706 on 2017/11/27.
  */
//下面相當(dāng)于java的靜態(tài)塊
object SessionFactory{
  var counts = 5;
  val buffer = new ArrayBuffer[Session](5)
  while (counts>0) {
    //給buffer緩存塞入5個(gè)Sessio對(duì)象
    val session = new Session
    buffer += session
    counts -= 1
  }

  //獲取session對(duì)象,相當(dāng)于java的靜態(tài)方法
  def getSession(): Unit ={
    //緩存中取session
    buffer.remove(0)
  }

  def main(args: Array[String]): Unit = {
    //單例對(duì)象,不需要new,用【類(lèi)名.方法】調(diào)用對(duì)象中的方法
    val session = SessionFactory.getSession
    println(session)
  }
}
class Session {
}

2、伴生對(duì)象
在Scala的類(lèi)中,與類(lèi)名相同的對(duì)象叫做伴生對(duì)象,類(lèi)和伴生對(duì)象之間可以相互訪(fǎng)問(wèn)私有的方法和屬性

/**
  * 伴生對(duì)象與類(lèi)之間私有屬性的訪(fǎng)問(wèn)
  * Created by 12706 on 2017/11/27.
  */
class Dog {
  private val name : String = "旺財(cái)"
  def bark(){
    //訪(fǎng)問(wèn)伴生對(duì)象的私有屬性
    println(Dog.voice)
  }
}
object Dog {
 private val voice : String = "wangwang"

  def main(args: Array[String]): Unit = {
    val dog = new Dog
    //訪(fǎng)問(wèn)對(duì)象的私有name屬性
    println(dog.name)
    dog.bark()
  }
}

2、apply方法

/**
  * apply方法:通常我們會(huì)在類(lèi)的伴生對(duì)象中定義apply方法,
  * 當(dāng)遇到類(lèi)名(參數(shù)1,...參數(shù)n)時(shí)apply方法會(huì)被調(diào)用
  * Created by 12706 on 2017/11/27.
  */
class Point {

  private var x : Int = 2

  println("主構(gòu)造器被調(diào)用")

  def this(x : Int){
    this()
    this.x = x
  }

}

object Point {

  def apply(): Unit ={
    println("apply()方法被調(diào)用")
  }

  def apply(x : Int, y : Int): Unit = {
    println("apply(x : Int, y : Int)方法被調(diào)用")
  }

  def apply(x : Int): Point = {
    println("apply(x : Int)方法被調(diào)用")
    new Point(x)
  }

  def main(args: Array[String]): Unit = {

    val p1 = new Point
    println("===================")
    //注意兩者區(qū)別,調(diào)用apply方法的時(shí)候不會(huì)執(zhí)行主構(gòu)造器方法
    val p2 = Point()

    val p3 = Point(3,4)
    println("===================")

    val p4 = Point(3)
    println(p4.x)
  }
}
輸出
主構(gòu)造器被調(diào)用
===================
apply()方法被調(diào)用
apply(x : Int, y : Int)方法被調(diào)用
===================
apply(x : Int)方法被調(diào)用
主構(gòu)造器被調(diào)用
3

4、應(yīng)用程序?qū)ο?br> Scala程序都必須從一個(gè)對(duì)象的main方法開(kāi)始,可以通過(guò)擴(kuò)展App特質(zhì),不寫(xiě)main方法。

/**
  * 應(yīng)用程序?qū)ο?,單例?duì)象(或者伴生對(duì)象)繼承App即可,App中定義了main方法被繼承過(guò)來(lái)了
  * 所以AppDemo中不需要寫(xiě)main方法了
  * Created by 12706 on 2017/11/27.
  */
object AppDemo extends App{
  val arr = Array(1,2,3,4)
  println(arr.toBuffer)
}

3、繼承
1、拓展類(lèi)
在Scala中擴(kuò)展類(lèi)的方式和Java一樣都是使用extends關(guān)鍵字,但是并沒(méi)有使用implements來(lái)實(shí)現(xiàn)接口,都是用extends。如果繼承一個(gè)類(lèi)的同時(shí)也實(shí)現(xiàn)了很多接口,那么用extends 父類(lèi) with 接口1 with 接口2 with…

2、方法的重寫(xiě)
方法重寫(xiě)就是子類(lèi)中對(duì)父類(lèi)的方法實(shí)現(xiàn)重寫(xiě)。
java中接口中都是抽象方法,但是scala中可以有實(shí)現(xiàn),而且關(guān)鍵字是trait稱(chēng)為特質(zhì)。但是重寫(xiě)一個(gè)非抽象方法必須使用override關(guān)鍵字。

3、類(lèi)型檢查和轉(zhuǎn)換
obj.isInstanceOf[C](scala中) ,obj instanceof C(java中)。obj是不是C類(lèi)型
obj.asInstanceOf[C](scala中),(C)obj(java中),obj類(lèi)型強(qiáng)轉(zhuǎn)為C類(lèi)型。
classOf[C](scala中),C.class。獲取C類(lèi)型

/**
  * Men是Human類(lèi)(繼承類(lèi)),同時(shí)擁有動(dòng)物的行為(實(shí)現(xiàn)接口)
  * Created by 12706 on 2017/11/27.
  */
//Human是類(lèi)必須接在extends后面
class Men extends Human with Animall{
  def say(): Unit = {
    println("大家好,我的名字叫:" + name)
  }

  //重寫(xiě)父類(lèi)已經(jīng)實(shí)現(xiàn)的方法需要加override關(guān)鍵字,父類(lèi)沒(méi)實(shí)現(xiàn)那么可加可不加
  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())

    //類(lèi)型檢查
    val b = man.isInstanceOf[Animall]
    println(b)

  }
}

abstract class Human {
  var name : String = _
  def say()
}

trait Animall {

  def getName(): String = {
    "monkey"
  }
}
輸出
大家好,我的名字叫:xiaoming
xiaoming
true

_ 對(duì)變量進(jìn)行默認(rèn)初始化,比如var i:Int=_

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Scala與Java的關(guān)系 Scala與Java的關(guān)系是非常緊密的?。?因?yàn)镾cala是基于Java虛擬機(jī),也就是...
    燈火gg閱讀 3,606評(píng)論 1 24
  • 1.1. 什么是Scala Scala是一種多范式的編程語(yǔ)言,其設(shè)計(jì)的初衷是要集成面向?qū)ο缶幊毯秃瘮?shù)式編程的各種特...
    文子軒閱讀 1,579評(píng)論 1 3
  • 今天一早起來(lái),外面宛如仙境,我拍了幾張,請(qǐng)看仙境小區(qū): 湖邊的櫻花沾了小水滴,葉子很美 樹(shù)枝上有個(gè)小蜘蛛,織了網(wǎng),...
    五月洛梅閱讀 186評(píng)論 0 2
  • 醫(yī)院里消毒水的氣味,總夾雜著陳舊的情緒 他們說(shuō)未來(lái)要遇到的人,會(huì)有各種途徑侵襲 打開(kāi)筆記本的那刻,誤打誤撞的你突然...
    火鍋不暖閱讀 1,001評(píng)論 5 7
  • ——————給我最?lèi)?ài)最?lèi)?ài)的老妹 10年的12月,你誕生在地球上,那時(shí)我還在學(xué)校,并...
    Switches閱讀 417評(píng)論 2 1

友情鏈接更多精彩內(nèi)容