真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

java中的Groovy和Scala類(lèi)知識(shí)點(diǎn)有哪些

這篇文章主要講解了“java中的Groovy和Scala類(lèi)知識(shí)點(diǎn)有哪些”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“java中的Groovy和Scala類(lèi)知識(shí)點(diǎn)有哪些”吧!

成都創(chuàng)新互聯(lián)專注于蘭西企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站建設(shè),商城網(wǎng)站建設(shè)。蘭西網(wǎng)站建設(shè)公司,為蘭西等地區(qū)提供建站服務(wù)。全流程定制開(kāi)發(fā),專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,成都創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

混入

混入的概念起源于 Flavors 語(yǔ)言(請(qǐng)參閱 參考資料)。這個(gè)概念的靈感來(lái)自于開(kāi)發(fā)該語(yǔ)言的辦公室附近的一家冰淇淋店。這家冰淇淋店提供了純口味的冰淇淋,以及客戶想要的其他任何的 “混合物”(糖果碎、糖屑、堅(jiān)果,等等)。

早期的一些面向?qū)ο笳Z(yǔ)言在單個(gè)代碼塊中共同定義某個(gè)類(lèi)的屬性和方法,所有類(lèi)定義是完整的。在其他語(yǔ)言中,開(kāi)發(fā)人員可以在一個(gè)地方定義屬性,但推遲方法的定義,并在適當(dāng)?shù)臅r(shí)候?qū)⑺鼈?“混合” 到類(lèi)中。隨著面向?qū)ο笳Z(yǔ)言的演變,混入與現(xiàn)代語(yǔ)言的配合方式的細(xì)節(jié)也在演變。

在 Ruby、Groovy 和類(lèi)似的語(yǔ)言中,作為一個(gè)接口和父類(lèi)之間的交叉,混入可以擴(kuò)充現(xiàn)有的類(lèi)層次結(jié)構(gòu)。像接口一樣,混入可以充當(dāng) instanceof 檢查的類(lèi)型,同時(shí)也要遵循相同的擴(kuò)展規(guī)則。您可以將無(wú)限數(shù)量的混入應(yīng)用于某一個(gè)類(lèi)。與接口不同的是,混入不僅指定了方法簽名,也可以實(shí)現(xiàn)簽名的行為。

在包括混入的第一種語(yǔ)言中,混入只包含方法,不包含狀態(tài),例如,成員變量?,F(xiàn)在很多語(yǔ)言(Groovy 也在其中)都包括有狀態(tài)的混入。Scala 的特征也以有狀態(tài)的方式進(jìn)行操作。

Groovy 的混入

Groovy 通過(guò) metaClass.mixin() 方法或 @Mixin 注解來(lái)實(shí)現(xiàn)混入。(@Mixin 注解依次使用 Groovy Abstract Syntax Tree (AST) 轉(zhuǎn)換,以支持所需的元編程管道。)清單 1 中的示例使用 metaClass.mixin() 讓 File 類(lèi)能夠創(chuàng)建 ZIP 壓縮文件:

清單 1. 將 zip() 方法混合到 File 類(lèi)中

class Zipper {def zip(dest) {new ZipOutputStream(new FileOutputStream(dest)).withStream { ZipOutputStream zos ->eachFileRecurse { f ->if (!f.isDirectory()) {zos.putNextEntry(new ZipEntry(f.getPath()))new FileInputStream(f).withStream { s ->zos << szos.closeEntry()}}}}}static {File.metaClass.mixin(Zipper)}}

在清單 1 中,我創(chuàng)建了一個(gè) Zipper 類(lèi),它包含新的 zip() 方法,以及將該方法添加到現(xiàn)有 File 類(lèi)的連接。zip() 方法的(不起眼的)Groovy 代碼以遞歸方式創(chuàng)建了一個(gè) ZIP 文件。清單的最后一部分通過(guò)使用靜態(tài)的初始化程序,將新方法添加到現(xiàn)有的 File 類(lèi)。在 Java 語(yǔ)言中,類(lèi)的靜態(tài)初始化程序在加載類(lèi)的時(shí)候運(yùn)行。靜態(tài)初始化程序是擴(kuò)充代碼的理想位置,因?yàn)樵谶\(yùn)行依賴于增強(qiáng)的任何代碼之前,應(yīng)確保先運(yùn)行初始化程序。在 清單 1 中,mixin() 方法將 zip() 方法添加到 File。

在 "沒(méi)有繼承性的擴(kuò)展,第 1 部分" 中,我介紹了兩種 Groovy 機(jī)制: ExpandoMetaClass 和類(lèi)別類(lèi),您可以使用它們?cè)诂F(xiàn)有類(lèi)上添加、更改或刪除方法。使用 mixin() 添加方法的最終結(jié)果與使用 ExpandoMetaClass 或類(lèi)別類(lèi)添加方法的最終結(jié)果相同,但它們的實(shí)現(xiàn)是不一樣的。請(qǐng)考慮清單 2 中混入示例:

清單 2. 混入操縱繼承層次結(jié)構(gòu)

import groovy.transform.ToStringclass DebugInfo {def getWhoAmI() {println "${this.class} <- ${super.class.name} <<-- ${this.getClass().getSuperclass().name}"}}@ToString class Person {def name, age}@ToString class Employee extends Person {def id, role}@ToString class Manager extends Employee {def suiteNo}Person.mixin(DebugInfo)def p = new Person(name:"Pete", age:33)def e = new Employee(name:"Fred", age:25, id:"FRE", role:"Manager")def m = new Manager(name:"Burns", id:"001", suiteNo:"1A")p.whoAmIe.whoAmIm.whoAmI

在清單 2 中,我創(chuàng)建了一個(gè)名為 DebugInfo 的類(lèi),其中包含一個(gè) getWhoAmI 屬性定義。在該屬性內(nèi),我打印出類(lèi)的一些詳細(xì)信息,比如當(dāng)前類(lèi)以及 super 和 getClass().getSuperClass() 屬性的父子關(guān)系說(shuō)明。接下來(lái),我創(chuàng)建一個(gè)簡(jiǎn)單的類(lèi)層次結(jié)構(gòu),包括 Person、Employee 和 Manager。

然后我將 DebugInfo 類(lèi)混合到駐留在層次結(jié)構(gòu)頂部的 Person 類(lèi)。由于 Person 具有 whoAmI 屬性,所以其子類(lèi)也具有該屬性。

在輸出中,可以看到(并且可能會(huì)感到驚訝),DebugInfo 類(lèi)將自己插入到繼承層次結(jié)構(gòu)中:

class Person <- DebugInfo <<-- java.lang.Objectclass Employee <- DebugInfo <<-- Personclass Manager <- DebugInfo <<-- Employee

混入方法必須適應(yīng) Groovy 中現(xiàn)有的復(fù)雜關(guān)系,以便進(jìn)行方法解析。清單 2 中的父類(lèi)的不同返回值反映了這些關(guān)系。方法解析的細(xì)節(jié)不屬于本文的討論范圍。但請(qǐng)小心處理對(duì)混入方法中的 this 和 super 值(及其各種形式)的依賴。

使用類(lèi)別類(lèi)或 ExpandoMetaClass 不影響繼承,因?yàn)槟皇菍?duì)類(lèi)進(jìn)行修改,而不是混入不同的新行為中。這樣做的一個(gè)缺點(diǎn)是,無(wú)法將這些更改識(shí)別為一個(gè)不同類(lèi)別的構(gòu)件。如果我使用類(lèi)別類(lèi)或 ExpandoMetaClass 將相同的三個(gè)方法添加到多個(gè)類(lèi)中,那么沒(méi)有特定的代碼構(gòu)件(比如接口或類(lèi)簽名)可以識(shí)別目前存在的共性?;烊氲膬?yōu)點(diǎn)是,Groovy 將使用混入的一切都視為一個(gè)類(lèi)別。

類(lèi)別類(lèi)實(shí)現(xiàn)的一個(gè)麻煩之處在于嚴(yán)格的類(lèi)結(jié)構(gòu)。您必須完全使用靜態(tài)方法,每個(gè)方法至少需要接受一個(gè)參數(shù),以代表正在進(jìn)行擴(kuò)充的類(lèi)型。元編程是最有用的,它可以消除這樣的樣板代碼。@Mixin 注釋的出現(xiàn)使得創(chuàng)建類(lèi)別并將它們混合到類(lèi)中變得更容易。清單 3(摘自 Groovy 文檔)說(shuō)明了類(lèi)別和混入之間的協(xié)同效應(yīng):

清單 3. 結(jié)合類(lèi)別和混入

interface Vehicle {String getName()}@Category(Vehicle) class Flying {def fly() { "I'm the ${name} and I fly!"}}@Category(Vehicle) class Diving {def pe() { "I'm the ${name} and I pe!"}}@Mixin([Diving, Flying])class JamesBondVehicle implements Vehicle {String getName() { "James Bond's vehicle" }}assert new JamesBondVehicle().fly() =="I'm the James Bond's vehicle and I fly!"assert new JamesBondVehicle().pe() =="I'm the James Bond's vehicle and I pe!"

在清單 3 中,我創(chuàng)建了一個(gè)簡(jiǎn)單的 Vehicle 接口和兩個(gè)類(lèi)別類(lèi)(Flying 和 Diving)。@Category 注釋關(guān)注樣板代碼的要求。在定義了類(lèi)別之后,我將它們混合成一個(gè) JamesBondVehicle,以便連接兩個(gè)行為。

類(lèi)別、ExpandoMetaClass 和混入在 Groovy 中的交集是積極的語(yǔ)言進(jìn)化的必然結(jié)果。三種技術(shù)明顯有重疊之處,但每種技術(shù)都有它們自身才能處理得最好的強(qiáng)項(xiàng)。如果從頭重新設(shè)計(jì) Groovy,那么作者可能會(huì)將三種技術(shù)的多個(gè)特性整合在一個(gè)機(jī)制中。

Scala 的特征

Scala 通過(guò)特征 實(shí)現(xiàn)了代碼重用,這是類(lèi)似于混入的一個(gè)核心語(yǔ)言特性。Scala 中的特征是有狀態(tài)的(它們可以同時(shí)包括方法和字段),它們與 Java 語(yǔ)言中的接口扮演相同的 instanceof 角色。特征和混入解決了多個(gè)相同的問(wèn)題,但特征在語(yǔ)言嚴(yán)謹(jǐn)性方面獲得了更多的支持。

In "Groovy、Scala 和 Clojure 中的共同點(diǎn),第 1 部分" 中,我使用了一個(gè)復(fù)數(shù)類(lèi)來(lái)說(shuō)明 Scala 中的操作符重載。我沒(méi)有在該類(lèi)中實(shí)現(xiàn)布爾比較操作符,因?yàn)?Scala 內(nèi)置的 Ordered 特征使得實(shí)現(xiàn)變得微不足道。清單 4 顯示了改進(jìn)的復(fù)數(shù)類(lèi),它利用了 Ordered 特征的優(yōu)勢(shì):

清單 4. 比較復(fù)數(shù)

final class Complex(val real:Int, val imaginary:Int) extends Ordered[Complex] {require (real != 0 || imaginary != 0)def +(operand:Complex) =new Complex(real + operand.real, imaginary + operand.imaginary)def +(operand:Int) =new Complex(real + operand, imaginary)def -(operand:Complex) =new Complex(real - operand.real, imaginary - operand.imaginary)def -(operand:Int) =new Complex(real - operand, imaginary)def *(operand:Complex) =new Complex(real * operand.real - imaginary * operand.imaginary,real * operand.imaginary + imaginary * operand.real)override def toString() =real + (if (imaginary < 0) "" else "+") + imaginary + "i"override def equals(that:Any) = that match {case other :Complex => (real == other.real) && (imaginary == other.imaginary)case _ => false}override def hashCode():Int =41 * ((41 + real) + imaginary)def compare(that:Complex) :Int = {def myMagnitude = Math.sqrt(this.real ^ 2 + this.imaginary ^ 2)def thatMagnitude = Math.sqrt(that.real ^ 2 + that.imaginary ^ 2)(myMagnitude - thatMagnitude).round.toInt}}

我在清單 4 中沒(méi)有實(shí)現(xiàn) >、<、<= 和 >= 運(yùn)算符,但我可以在復(fù)數(shù)實(shí)例中調(diào)用它們,如清單 5 所示:

清單 5. 測(cè)試比較

class ComplexTest extends FunSuite {test("comparison") {assert(new Complex(1, 2) >= new Complex(3, 4))assert(new Complex(1, 1) < new Complex(2,2))assert(new Complex(-10, -10) > new Complex(1, 1))assert(new Complex(1, 2) >= new Complex(1, 2))assert(new Complex(1, 2) <= new Complex(1, 2))}}

因?yàn)椴恍枰捎脭?shù)學(xué)上定義的技術(shù)來(lái)比較復(fù)數(shù),所以在 清單 4 中,我使用了一個(gè)被人們普遍接受的算法來(lái)比較數(shù)字的大小。我使用 Ordered[Complex] 特征來(lái) extend 類(lèi)定義,它混入了參數(shù)化的類(lèi)的布爾運(yùn)算符。為了讓特征可以正常工作,注入的運(yùn)算符必須比較兩個(gè)復(fù)數(shù),這是 compare() 方法的目的。如果您嘗試 extendOrdered 特征,但不提供所需的方法,那么編譯器消息會(huì)通知您,因?yàn)槿鄙偎璧姆椒?,所以必須將您的?lèi)聲明為 abstract。

在 Scala 中,特征有兩個(gè)明確定義的作用:豐富接口和執(zhí)行可堆疊的修改。

豐富接口

在設(shè)計(jì)接口時(shí),Java 開(kāi)發(fā)人員面臨著一個(gè)取決于便利性的難題:應(yīng)該創(chuàng)建包含很多方法的富 接口,還是創(chuàng)建只有幾個(gè)方法的瘦 接口?富接口對(duì)于其消費(fèi)者更方便一些,因?yàn)樗峁┝藦V泛的方法調(diào)色板,但方法的絕對(duì)數(shù)量使得接口更加難以實(shí)現(xiàn)。瘦接口的問(wèn)題剛好相反。

特征可以解決使用富接口還是薄接口的這種兩難問(wèn)題。您可以在瘦接口中創(chuàng)建核心功能,然后使用特征擴(kuò)充它,以提供更豐富的功能。例如,在 Scala 中,Set 特征實(shí)現(xiàn)了一個(gè)設(shè)置好的共享功能,您選擇的子特征( mutable 或 immutable)已經(jīng)決定了設(shè)置是否可變。

可堆疊的修改

Scala 中的特征的另一個(gè)常見(jiàn)用途是可堆疊的修改。利用特征,您可以修改現(xiàn)有的方法并添加新的方法,super 提供了對(duì)可以鏈接回以前的特征實(shí)現(xiàn)的訪問(wèn)。

清單 6 通過(guò)一些隊(duì)列說(shuō)明了可堆疊的修改:

清單 6. 構(gòu)建可堆疊的修改

abstract class IntQueue {def get():Intdef put(x:Int)}import scala.collection.mutable.ArrayBufferclass BasicIntQueue extends IntQueue {private val buf = new ArrayBuffer[Int]def get() = buf.remove(0)def put(x:Int) { buf += x }}trait Squaring extends IntQueue {abstract override def put(x:Int) { super.put(x * x) }}

在清單 6 中,我創(chuàng)建一個(gè)簡(jiǎn)單的 IntQueue 類(lèi)。然后,我構(gòu)建一個(gè)可變的版本,該版本中包括 ArrayBuffer。Squaring 特征擴(kuò)展了所有 IntQueue,并在值被插入隊(duì)列中時(shí)自動(dòng)對(duì)其進(jìn)行平方計(jì)算。在 Squaring 特征內(nèi)對(duì) super 的調(diào)用提供對(duì)堆棧中前面的特性的訪問(wèn)。除了第一個(gè)方法之外,只要每個(gè)被重寫(xiě)的方法調(diào)用 super,修改堆棧就會(huì)一個(gè)一個(gè)地堆疊上去,如清單 7 所示:

清單 7. 構(gòu)建堆疊的實(shí)例

object Test {def main(args:Array[String]) {val queue = (new BasicIntQueue with Squaring)queue.put(10)queue.put(20)println(queue.get()) // 100println(queue.get()) // 400}}

super清單 6 中對(duì) super 的使用說(shuō)明了特征和混入之間的重要區(qū)別。因?yàn)槟趧?chuàng)建原始的類(lèi)后(確實(shí))混入了它們,所以混入必須解決類(lèi)層次結(jié)構(gòu)中的當(dāng)前位置上的潛在不確定性。特征在創(chuàng)建類(lèi)的時(shí)候已被線性化;編譯器解決了什么是 super 的問(wèn)題,沒(méi)有不確定性。嚴(yán)格定義的復(fù)雜規(guī)則(這超出了本文的范圍)控制了線性化在 Scala 中的工作方式。特征還為 Scala 解決了鉆石問(wèn)題。當(dāng) Scala 跟蹤方法的源和解析時(shí),不可能出現(xiàn)不確定性,因?yàn)樵撜Z(yǔ)言定義了明確的規(guī)則來(lái)處理解析。

感謝各位的閱讀,以上就是“java中的Groovy和Scala類(lèi)知識(shí)點(diǎn)有哪些”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)java中的Groovy和Scala類(lèi)知識(shí)點(diǎn)有哪些這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!


當(dāng)前文章:java中的Groovy和Scala類(lèi)知識(shí)點(diǎn)有哪些
本文網(wǎng)址:http://weahome.cn/article/gjhisp.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部