面向物件編程
包
語法
package com.pac1.pac2.pac3
package com
package pac1 {
package pac2 {
package pac3 {
object ScalaPackage {
def test(): Unit = {
println("test...")
}
}
}
}
}
注意
-
包和類的物理路徑沒有關系
-
同一個原始碼檔案中子包可以直接訪問父包中的內容,而無需import
-
package也可以看作物件,并宣告屬性和函式
package big { class Test{ def test() :Unit = { printf("test...") } } package object ob_pack{ val name : String = "ob_pack" def getname(): String = { name } } package ob { object ob01 { def main(args: Array[String]): Unit = { new Test().test() printf(ob_pack.getname()) } } } }
匯入
語法
import java.util.List
import java.util._ // Scala中使用下劃線代替Java中的星號
注意
-
import語法可以在任意位置使用
-
可以導包,而不是導類
object ScalaImport{ def main(args: Array[String]): Unit = { import java.util new util.ArrayList() } } -
可以在同一行中匯入相同包中的多個類,簡化代碼
import java.util.{List, ArrayList} -
可以屏蔽某個包中的類
import java.sql.{ Date=>_, Array=>_, _ } -
可以給類起別名,簡化使用
import java.util.{ArrayList=>AList} -
可以使用類的絕對路徑而不是相對路徑
import _root_.java.util.ArrayList -
默認情況下,Scala中會匯入如下包和物件
import java.lang._ import scala._ import scala.Predef._
類
語法
// 宣告類:訪問權限 class 類名 { 類主體內容 }
class User {
// 類的主體內容
}
// 物件:new 類名(引數串列)
new User()
注意
- 一個源檔案中可以宣告多個公共類
屬性
語法
class User {
var name : String = _ // 類屬性其實就是類變數
var age : Int = _ // 下劃線表示類的屬性默認初始化
}
注意
-
屬性其實在編譯后也會生成方法
public static class User { private String name; private int age; public String name() { return this.name; } public void name_$eq(final String x$1) { this.name = x$1; } public int age() { return this.age; } public void age_$eq(final int x$1) { this.age = x$1; } }
訪問權限
語法
private : 私有訪問權限 => 同類
private[包名]: 包訪問權限 => 同包,包私有
protected : 受保護權限,不能同包 => 受保護的, 同類,子類,沒有同包
: 公共訪問權限
方法
類的方法其實就是函式,所以宣告方式完全一樣,但是必須通過使用物件進行呼叫
object ScalaMethod{
def main(args: Array[String]): Unit = {
val user = new User // new 物件 才可以使用方法
user.login("zhangsan", "000000")
}
}
class User {
def login( name:String, password:String ): Boolean = {
false
}
}
物件
語法
val / var 物件名 [:型別] = new 型別()
var user : User = new User()
補充
生成物件的操作
- 反射
- new
- 反序列化
- clone
構造方法(class)
語法
構造物件也需要呼叫類的構造方法來創建,并且一個類中可以有任意多個不相同的構造方法,這些構造方法可以分為2大類:主建構式與輔助建構式
class User() { // 主建構式 ----用于完成類的初始化操作的構造方法稱之為主構造方法
var username : String = _ // TODO 在構造引數前使用var或val宣告
def this( name:String ) { // 輔助建構式,使用this關鍵字宣告 ----其他的構造方法就稱之為輔助構造方法
this() // 輔助構造方法在執行之前,應該首先呼叫主構造方法完成類的初始化
username = name
}
def this( name:String, password:String ) {
this(name) // 構造器呼叫其他另外的構造器,要求被呼叫構造器必須提前宣告
}
}
// 輔助構造方法可以多載的,并且可以互相呼叫,但是呼叫的輔助構造方法應該提前宣告
def main(args: Array[String]): Unit = {
new User("zhangsan"); // 先執行父類構造方法
// * 子類所有的 建構式 默認呼叫父類的無參建構式(其實是默認省略掉了一行代碼:super(););省略掉的這行super()代碼可以自行添加到建構式的第一行(必須是第一行,否則報錯)
// aaaaa
// ccccc
new User()
//aaaaa
//ccccc
//ddddd
}
class Person(s:String) {
println("aaaaa")
def this() {
this("lisi")
println("bbbbb")
}
}
class User(var name:String) extends Person(name){
println("ccccc")
def this() {
this("wangwu")
println("ddddd")
}
}
伴生類與伴生物件(object)
構造方法私有化: 在引數串列前增加private關鍵字
宣告一個公共的,靜態的,回傳本型別的方法,用于獲取物件
scala中沒有靜態語法,但是可以直接使用java中的靜態操作
scala采用了一種特殊的處理方式來代替靜態語法 :object
object關鍵字可以用于創建物件,物件的名字就是宣告的名字
使用object關鍵字宣告的類和物件有關系的,這個物件等同于伴隨著這個類創建時所產生的,所以將這個物件稱之為:伴生物件,這個類稱之為伴生類,伴生物件就是一個物件,可以訪問伴生類中的所有東西,包括私有的,伴生物件其實就是馬丁模擬靜態語法所產生的,一般寫代碼時,將靜態語法操作的代碼寫在伴生物件中,將成員方法或屬性寫在伴生類中
// 伴生類
class Person private () {
}
// 伴生物件
// Person.class
// Person$.class
object Person {
def getInstance() : Person = {
new Person()
}
}
- scala中伴生物件就是單例的
- 伴生物件只需要宣告即可,無需構建,所以不需要構造引數串列
- 單例模式存在一個問題:創建的物件不會被回收,需要顯示地回收(設定為null)
- 如果伴生物件中構建物件的方法名成為apply,編譯器可以自動識別的,所以這個方法名可以省略的
//val test1: Test = Test.apply()
//val test1 = new Test() // 呼叫類的構造方法
//val test2 = Test() // 呼叫的是伴生物件的apply方法
//val test3 = Test // 伴生物件本體
class Test() {
println("ttttt")
}
object Test {
def apply() = {
println("apply")
//new Test()
}
}
繼承
class Person {
}
class User extends Person { // 單繼承
}
封裝
封裝就是把抽象出的資料和對資料的操作封裝在一起,資料被保護在內部,程式的其它部分只有通過被授權的操作(成員方法),才能對資料進行訪問,
- 將屬性進行私有化
- 提供一個公共的set方法,用于對屬性賦值
- 提供一個公共的get方法,用于獲取屬性的值
抽象
-
所謂的抽象其實就是不完整
-
抽象類,抽象方法
-
抽象類沒有辦法直接實體化,需要由子類繼承后完成實體化操作
-
子類繼承抽象類后,可以宣告為抽象類,也可以將父類的抽象方法補充完整,
-
scala中不完整的方法就是抽象,所以無需增加abstract關鍵字,
-
將一個不完整的類稱之為抽象類,
abstract class Person { } -
如果一個方法只有宣告而沒有實作,那么是抽象方法,因為它不完整,
abstract class Person { def test():Unit } -
如果一個屬性只有宣告沒有初始化,那么是抽象屬性,因為它不完整,
abstract class Person { var name:String } -
子類如果繼承抽象類,必須實作抽象方法或補全抽象屬性,否則也必須宣告為抽象的,因為依然不完整,
abstract class Person { // 抽象屬性:只有宣告,沒有初始化 // 編譯時,不會在類中宣告屬性,而是會宣告屬性的set,get方法,并且是抽象的, var name:String } class User extends Person { // 屬性:編譯時,會在類中宣告私有屬性,同時提供屬性的set,get方法,并且為公共的, var name : String = "zhangsan" } -
子類重寫父類的抽象方法,直接補充完整即可
-
子類重寫父類的完整方法,必須添加override關鍵字
-
開發時,推薦,只要重寫,都添加override
abstract class User { def test(): Unit = { } def fun():Unit } class Child extends User { override def test(): Unit = { } override def fun():Unit = { } } -
子類可以重寫父類的抽象屬性
def main(args: Array[String]): Unit = { // TODO 面向物件 - 抽象 // 子類可以重寫父類的抽象屬性,補充完整即可 // 子類可以重寫父類的完整屬性,那么必須要添加override關鍵字 // println(new Child().age) println(new Child().test) } abstract class User { var name : String val age : Int = 10 def test(): Unit = { //age = 30 // 對屬性的賦值其實等同于呼叫屬性的set方法 println(age) // 對屬性的方法其實等同于呼叫屬性的get方法 } } class Child extends User { var name : String = "zhangsan" // 重寫 override val age : Int = 20 }
特質
語法
- 將多個物件中相同的特征,從物件中剝離出來,形成獨立的一個結構,稱之為trait(特征)
- 如果一個物件符合這個特征,那么可以將這個特征加入到這個物件,這個加入的程序,稱之為混入(extends)
- 如果一個類只有一個特征時,采用extends關鍵字進行混入
- 但是一個類如果有多個特征,這個時候,第一個特征采用extends,后續采用with
- 如果類存在父類的場合,并同時具備了某個特征,需要使用extends關鍵字繼承父類,使用with關鍵字來混入特征
trait 特質名稱
class 類名 extends 父類(特質1) with 特質2 with特質3
trait eat {
def eat():Unit
}
trait Runnable {
def run():Unit
}
class Person extends Object with Runnable {
override def run(): Unit = {
println("run...")
}
}
class Dog extends Runnable {
override def run(): Unit = {
println("run...")
}
}
注意
-
動態混入
object ScalaTrait{ def main(args: Array[String]): Unit = { val mysql = new MySQL with Operator //使用中混入 mysql.insert() } } trait Operator { def insert(): Unit = { println("insert data...") } } class MySQL { } -
初始化疊加
object ScalaTrait{ def main(args: Array[String]): Unit = { val mysql = new MySQL } } trait Operator { println("operator...") } trait DB { println("db...") } class MySQL extends DB with Operator{ println("mysql...") } -
功能疊加
-
java中不能類的多繼承 : 磚石問題
scala采用了一種功能疊加的方式解決磚石問題
super不是父特質的意思,是上一級(上一個)的意思object ScalaTrait { def main(args: Array[String]): Unit = { val mysql: MySQL = new MySQL mysql.operData() } } trait Operate{ def operData():Unit={ println("操作資料,,") } } trait DB extends Operate{ override def operData(): Unit = { print("向資料庫中,,") super.operData() } } trait Log extends Operate{ override def operData(): Unit = { super.operData() } } class MySQL extends DB with Log { } -
初始化問題
父類的特質 > 父類 > 特質1, 特質2 > 當前類new User() // bbbb // dddd // aaaa // cccc trait Test extends Test1{ println("aaaa") } trait Test1 { println("dddd") } class Person{ println("bbbb") } class User extends Person with Test with Test1 { println("cccc") }
補充
-
型別檢查和轉換
class Person{ } object Person { def main(args: Array[String]): Unit = { val person = new Person //(1)判斷物件是否為某個型別的實體 val bool: Boolean = person.isInstanceOf[Person] if ( bool ) { //(2)將物件轉換為某個型別的實體 val p1: Person = person.asInstanceOf[Person] println(p1) } //(3)獲取類的資訊 val pClass: Class[Person] = classOf[Person] println(pClass) } } -
列舉類和應用類
object Test { def main(args: Array[String]): Unit = { println(Color.RED) } } // 列舉類 object Color extends Enumeration { val RED = Value(1, "red") val YELLOW = Value(2, "yellow") val BLUE = Value(3, "blue") } // 應用類 object AppTest extends App { println("application"); } -
Type定義新型別
object Test { def main(args: Array[String]): Unit = { type S = String var v : S = "abc" } } -
修改不可變字串內容 -- 不可變指的是地址
val s = " a b " // 反射:型別資訊 // 鏡子 val stringClass: Class[String] = classOf[String] val field: Field = stringClass.getDeclaredField("value") field.setAccessible(true) val obj = field.get(s) val chars: Array[Char] = obj.asInstanceOf[Array[Char]] chars(2) = 'D' println(s)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/514280.html
標籤:Scala
上一篇:序列化組件
下一篇:C語言小白刷題
