scala 基本介紹與用法(三)

目錄

 

二十二、類和對象

創建類和對象

二十三、定義和訪問成員變量

二十四、使用下劃線初始化成員變量

二十五、定義成員方法

二十六、訪問修飾符

二十七、類的構造器

主構造器

輔助構造器

二十八、單例對象

二十九、工具類案例

三十、main方法

定義main方法

實現App Trait來定義入口

三十一、伴生對象

定義伴生對象

private[this]訪問權限


二十二、類和對象

scala是支持面向對象的,也有類和對象的概念。我們依然可以基於scala語言來開發面向對象的應用程序。

創建類和對象

object _01ClassDemo {
 
// 創建類
 class Person{}

 
def main(args: Array[String]): Unit = {
   
// 創建對象
   val p = new Person()
   
println(p)
}
}

object _02ClassDemo {
​
 // 創建類,省略花括號
 class Person
​
 def main(args: Array[String]): Unit = {
   // 創建對象,省略括號
   val person = new Person
}
}

二十三、定義和訪問成員變量

一個類會有自己的屬性,例如:人這樣一個類,有自己的姓名和年齡。在類中定義、和訪問成員變量

object _03ClassDemo {
 
class Person {
   
// 定義成員變量
   var name = ""
   var age = 0
}

 def main(args: Array[String]): Unit = {
   // 創建Person對象
   val person = new Person
   person.name = "zhangsan"
   person.age = 20
​
   // 獲取變量值
   println(person.name)
   println(person.age)
}
}

二十四、使用下劃線初始化成員變量

scala中有一個更簡潔的初始化成員變量的方式,可以讓代碼看起來更加簡潔。

在定義var類型的成員變量時,可以使用_來初始化成員變量

  • String => null
  • Int => 0
  • Boolean => false
  • Double => 0.0
  • ...

val類型的成員變量,必須要自己手動初始化

object _04ClassDemo {
​
 class Person{
   // 使用下劃線進行初始化
   var name:String = _
   var age:Int = _
}
​
 def main(args: Array[String]): Unit = {
   val person = new Person
   
   println(person.name)
   println(person.age)
}
}

二十五、定義成員方法

類可以有自己的行爲,scala中也可以通過定義成員方法來定義類的行爲。

使用def來定義成員方法

  1. 創建一個該類的對象,並調用printHello方法

步驟

  1. 1、創建一個Object,添加main方法
  2. 2、創建Customer類,添加成員變量、成員方法
  3. 3、在main方法中創建Customer類對象,設置成員變量值(張三、男)
  4. 4、調用成員方法
object _05ClassDemo {
​
 class Customer {
   var name:String = _
   var sex:String = _
​
   // 定義成員方法
   def sayHi(msg:String) = {
     println(msg)
  }
}
​
 def main(args: Array[String]): Unit = {
   val customer = new Customer
   customer.name = "張三"
   customer.sex = "男"
   customer.sayHi("你好")
}
}

二十六、訪問修飾符

Java一樣,scala也可以通過訪問修飾符,來控制成員變量和成員方法是否可以被訪問。

定義

可以在成員前面添加private/protected關鍵字來控制成員的可見性。

scala中,沒有public關鍵字,任何沒有被標爲private或protected的成員都是公共的

案例

定義一個Person類

 

在main方法中創建該類的對象,測試是否能夠訪問到私有成員

object _02AccessDemo {
​
 class Person {
   // 定義私有成員變量
   private var name:String = _
   private var age:Int = _
​
   def getName() = name
   def setName(name:String) = this.name = name
   def getAge() = age
   def setAge(age:Int) = this.age = age
​
   // 定義私有成員方法
   private def getNameAndAge = {
     name -> age
  }
}
​
 def main(args: Array[String]): Unit = {
   val person = new Person
   person.setName("張三")
   person.setAge(10)
​
   println(person.getName())
   println(person.getAge())
}
}

二十七、類的構造器

當創建類對象的時候,會自動調用類的構造器。之前使用的都是默認構造器,

主構造器

Java的構造器,有構造列表和構造代碼塊

class Person {
   
// 成員變量
   private String name;
   
private Integer age;

   
// Java構造器
   public Person(String name, Integer age) {
       
// 初始化成員變量
       this.name = name;
       
this.age = age;
  }
}

在scala中, 可以使用更簡潔的語法來實現。

語法

class 類名(var/val 參數名:類型 = 默認值, var/val 參數名:類型 = 默認值){
   
// 構造代碼塊
}

  1. 主構造器的參數列表是直接定義在類名後面,添加了val/var表示直接通過主構造器定義成員變量
  2. 構造器參數列表可以指定默認值
  3. 創建實例,調用構造器可以指定字段進行初始化
  4. 整個class中除了字段定義和方法定義的代碼都是構造代碼

示例

  1. 定義一個Person類,通過主構造器參數列表定義姓名和年齡字段,並且設置它們的默認值
  2. 在主構造器中輸出"調用主構造器"
  3. 創建"張三"對象(姓名爲張三,年齡爲20),打印對象的姓名和年齡
  4. 創建"空"對象,不給構造器傳入任何的參數,打印對象的姓名和年齡
  5. 創建"man40"對象,不傳入姓名參數,指定年齡爲40,打印對象的姓名和年齡

scala的主構造器

object _06ConstructorDemo {

  // 定義類的主構造器
  // 指定默認值
  class Person(var name:String = "", var age:Int = 0) {
    println("調用主構造器")
  }

  def main(args: Array[String]): Unit = {
    // 給構造器傳入參數
    val zhangsan = new Person("張三", 20)
    println(zhangsan.name)
    println(zhangsan.age)

    println("---")

    // 不傳入任何參數
    val empty = new Person
    println(empty.name)
    println(empty.age)

    println("---")

    // 指定字段進行初始化
    val man40 = new Person(age = 40)
    println(man40.name)
    println(man40.age)
  }
}

輔助構造器

除了主構造器之外的構造器稱爲輔助構造器

例如:允許通過多種方式,來創建對象,這時候就可以定義其他更多的構造器。

語法

  • 定義輔助構造器與定義方法一樣,也使用def關鍵字來定義
  • 這個方法的名字爲this

def this(參數名:類型, 參數名:類型) {

    // 第一行需要調用主構造器或者其他構造器

    // 構造器代碼

}

輔助構造器的第一行代碼,必須要調用主構造器或者其他輔助構造器

示例

  1. 定義一個Customer類,包含一個姓名和地址字段
  2. 定義Customer類的主構造器(初始化姓名和地址)
  3. 定義Customer類的輔助構造器,該輔助構造器接收一個數組參數,使用數組參數來初始化成員變量
  4. 使用Person類的輔助構造器來創建一個"zhangsan"對象
  5. 姓名爲張三
  6. 地址爲北京
  7. 打印對象的姓名、地址
object _07ConstructorDemo {
  class Customer(var name:String = "", var address:String = "") {
    // 定義輔助構造器
    def this(arr:Array[String]) = {
      // 輔助構造器必須要調用主構造器或者其他輔助構造器
      this(arr(0), arr(1))
    }
  }

  def main(args: Array[String]): Unit = {
    val zhangsan = new Customer(Array("張三", "北京"))

    println(zhangsan.name)
    println(zhangsan.address)
  }
}

二十八、單例對象

scala中沒有Java中的靜態成員,若想要定義類似於Java的static變量、static方法,就要使用到scala中的單例對象——object.

定義單例對象

單例對象表示全局僅有一個對象(類似於Java static概念)

  • 定義單例對象和定義類很像,就是把class換成object
  • 在object中定義的成員變量類似於Java的靜態變量
  • 可以使用object直接引用成員變量

示例

  1. 定義一個Dog單例對象,保存狗有幾條腿
  2. 在main方法中打印狗腿的數量
object _08ObjectDemo {

  // 定義一個單例對象
  object Dog {
    // 定義腿的數量
    val LEG_NUM = 4
  }

  def main(args: Array[String]): Unit = {
    println(Dog.LEG_NUM)
  }
}

在單例對象中定義成員方法

  • 在object中定義的成員方法類似於Java的靜態方法

示例

  1. 設計一個單例對象,定義一個能夠打印分割線(15個減號)的方法
  2. 在main方法調用該方法,打印分割線
object _09ObjectDemo {
  object PrintUtil {
    // 打印分割線
    def printSpliter() = {
      // 字符串乘法,表示返回多少個字符串
      println("-" * 10)
    }
  }

  def main(args: Array[String]): Unit = {
    PrintUtil.printSpliter()
  }
}

二十九、工具類案例

  1. 編寫一個DateUtil工具類專門用來格式化日期時間
  2. 定義一個方法,用於將日期(Date)轉換爲年月日字符串,例如:2030-10-05

步驟

  1. 定義一個DateUtil單例對象,定義日期格式化方法(format)
  2. 使用SimpleDateFormat將日期轉換爲字符串
object _10ObjectDemo {

  object DateUtils {
    // 在object中定義的成員變量,相當於Java中定義一個靜態變量
    // 定義一個SimpleDateFormat日期時間格式化對象
    val simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm")

    // 相當於Java中定義一個靜態方法
    def format(date: Date) = simpleDateFormat.format(date)
  }

  // main是一個靜態方法,所以必須要寫在object中
  def main(args: Array[String]): Unit = {
    println(DateUtils.format(new Date()))
  }
}

三十、main方法

scala和Java一樣,如果要運行一個程序,必須有一個main方法。在Java中main方法是靜態的,而在scala中沒有靜態方法。在scala中,這個main方法必須放在一個單例對象中。

定義main方法

main方法

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

    // 方法體

}

示例

創建一個單例對象,在該單例對象中打印"hello, scala"

object Main5 {
  def main(args:Array[String]) = {
    println("hello, scala")
  }
}

實現App Trait來定義入口

創建一個object,繼承自App Trait(特質),然後將需要編寫在main方法中的代碼,寫在object的構造方法體內。

object 單例對象名 extends App {

    // 方法體

}

示例

繼承App特質,來實現一個入口。同樣輸出"hello, scala"

object Main5 extends App {
  println("hello, scala")
}

三十一、伴生對象

在Java中,經常會有一些類,同時有實例成員又有靜態成員。例如:

public class CustomerService {

    private static String SERVICE_NAME = "CustomerService";

    public void save() {
        // 保存客戶
        System.out.println(SERVICE_NAME + ":保存客戶");
    }

    public static void main(String[] args) {
        new CustomerService().save();
    }
}

在scala中,要實現類似的效果,可以使用伴生對象來實現。

定義伴生對象

一個class和object具有同樣的名字。這個object稱爲伴生對象,這個class稱爲伴生類

  • 伴生對象必須要和伴生類一樣的名字
  • 伴生對象和伴生類在同一個scala源文件中
  • 伴生對象和伴生類可以互相訪問private屬性

示例

  1. 編寫一個CustomerService類,有一個save方法,打印
  2. 服務類名稱:保存客戶
  3. 編寫一個CustomerService伴生對象,定義一個私有變量,用於保存服務類名稱
  4. 創建CustomerService對象,調用save方法
object _11ObjectDemo {

  class CustomerService {
    def save() = {
      println(s"${CustomerService.SERVICE_NAME}:保存客戶")
    }
  }

  // CustomerService的伴生對象
  object CustomerService {
    private val SERVICE_NAME = "CustomerService"
  }

  def main(args: Array[String]): Unit = {
    val customerService = new CustomerService()
    customerService.save()
  }
}

private[this]訪問權限

如果某個成員的權限設置爲private[this],表示只能在當前類中訪問。伴生對象也不可以訪問

示例

  1. 定義一個Person類,包含一個name字段
  2. 定義Person類的伴生對象,定義printPerson方法
  3. 測試伴生對象是否能訪問private[this]權限的成員
class Person(private[this] var name:String)
 
  object Person {
    def printPerson(person:Person): Unit = {
      println(person.name)
    }
  }
 
  def main(args: Array[String]): Unit = {
    val person = new Person("張三")
    Person.printPerson(person)
  }

上述代碼,會編譯報錯。但移除掉[this]就可以訪問了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章