Scala入门到精通——第七节:类和对象(二)
本節主要內容
單例對象
在某些應用場景下,我們可能不需要創建對象,而是想直接調用方法,但是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
總結
以上是生活随笔為你收集整理的Scala入门到精通——第七节:类和对象(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Scala入门到精通——第六节:类和对象
- 下一篇: Scala入门到精通——第八节 包和引入