Scala筆記

1、伴生對象

形如:
有一個類
class Test{
}
一個object和該類同名
object Test{
}

object Test的作用類似于靜態類(工具類),其中的所有成員都是靜態的,在object Test中可以直接訪問class Test的成員;反之,class Test中要通過object Test來引用其成員例如使用Test.的方式

2、apply方法

class中的apply:是一個比較特殊的方法,通過這個class new 出來的對象,可以直接通過對象(),這樣的方式來調用apply方法

object中的apply:比較常用,例如,通常使用數組時是下面這樣的代碼:

val arr = new Array[Int](3)
arr(0) = 1
arr(1) = 2
arr(2) = 3

但是,在scala中可以通過伴生對象的apply方法,我們可以很方便的構建類的對象,而不必知道和操作這個過程,如下:

val arr = Array(1,2,3)

通過伴生對象的apply方法,我們可以很方便的構建類的對象,而不必知道和操作這個過程,在apply方法中其實也是new出一個Array,并在其中做好了初始化操作
源代碼如下:

/** Creates an array of `Int` objects */// Subject to a compiler optimization in Cleanup, see above.def apply(x: Int, xs: Int*): Array[Int] = {val array = new Array[Int](xs.length + 1)array(0) = xvar i = 1for (x <- xs.iterator) { array(i) = x; i += 1 }array}

3、繼承

沒啥好說的,概念和其他語言一樣,只是語法有點區別:

class Father(name:String){
...
}
//構造子類的時候會先構造父類,所以要將父類構造函數需要的參數給它
class Son(name:String,age:Int) extends Father(name){
...
}

4、trait特質

trait可以當接口來用,但是和其他語言的接口有些不同,trait里面竟然還可以有方法的定義!
那么這樣和抽象類不是一樣的了,干嘛還要trait?
Scala中也是單繼承,也就是說一個類只能繼承一個父類,需要有很多子類的特性的時候就可以通過繼承多個trait來實現(可以把抽象類看成是一個統一的模板,trait則是其他七七八八的裝飾,可加可減靈活性高)

在Scala中如果一個class,或者一個trait直接繼承了另外一個trait,那么語法是一樣的:

trait Test{
...
}class Test1 extends Test{
...
}

當多重繼承時,trait要使用with關鍵字,構造順序從左往右,且不重復構造:

class Human{...}
trait ITeacher extends Human{...}
trait IBasketballPlayer extends Human{...}
class BasketballTeacher extends Human with ITeacher with IBasketballPlayer{...}

由于ITeacher和IBasketballPlayer都繼承了Human,理論上在構造他們的時候會去構造他們的父類,也就是Human,但是由于Human之間在構造BasketballTeacher 的時候已經構造過了,所以這里不再重復構造

上面代碼演示的是在定義class的時候混入trait
實際上也可以在new object的時候使用,這樣可以在具體的場景中定義具體處理的對象(和定義class的時候直接混入的區別是,前者new出來的所有object都帶有trait特質的,后者只作用在一個單一的object):

class Human{...}
trait ITeacher extends Human{...}
trait IBasketballPlayer extends Human{...}val t1 = new Human with ITeacher with IBasketballPlayer{
//如果有抽象方法,在此重寫
}

需要注意的是,混入的trait必須都繼承自同一個父類

trait的AOP實現:

trait DoSomething {def work
}class Do extends DoSomething{override def work: Unit = {println("working!")}
}trait BeforeAndAfter extends DoSomething {abstract override def work: Unit = {println("init...")super.workprintln("destroy...")}
}object test {def main(args: Array[String]) {val worker = new Do with BeforeAndAfterworker.work}
}

上面的代碼中,使用trait實現了一個簡單的AOP編程實例

首先定義了一個trait DoSomething,里面有一個抽象方法work
class Do繼承自DoSomething,并實現了具體的work方法

這時new一個Do的object之后調用work應該打印出一行記錄
之后定義了另外一個trait BeforeAndAfter,也繼承了DoSomething并重寫work

在其重寫的方法中將父trait的work方法放在初始化和銷毀的操作之間,由于父trait的work方法是抽象的,此時又調用了這個抽象方法,所以這個重寫的work仍然是抽象的,要加上abstract關鍵字

在new Do的object的時候混入這個trait就可以實現AOP,代碼執行過程應該是這樣的:
1、調用worker的work方法,由于混入了trait,所以實際調用的是這個trait里面的work
2、這個trait里面的work先進行了初始化操作,然后調用父trait的work,而這個方法的具體實現是在Do類中完成的,所以又調用了Do類中的具體work實現
3、work調用完成之后,進行銷毀操作

5、包對象

包對象的定義及作用如下:

//這是一個包對象
package obejct Person{...}
//這是一個包的定義
package Person{
//此時,在這個包的作用于范圍之內,可以直接訪問包對象的成員
}//使用這種語法的import意思是將scala包中的StringBuilder隱藏起來不使用(使用別的包的StringBuilder)
import scala.{StringBuilder => _}

6、文件操作

//讀取本地文件
val localFile = Source.fromFile("file path")
val lines = localFile.getLines
//讀取網絡文件
val networkFile = Source.fromURL("file url")
//創建一個寫入器
val writer = new PrintWriter(new File("file path"))
writer.println("something to write")
writer.close
//控制臺讀取
Console.readLine

7、正則表達式

//可以直接使用字符串.r的方式返回一個Regex對象
val regex1 = "[0-9]+".r
//三個引號表示表達式中的符號都是原意,而不是轉義符(如\)
val regex2 = """\s+[0-9]+\s+""".r
//Regex對象可以直接調用findAllIn/findFirstIn等方法
regex1.findAllIn("1234 dqd qwdq")//該方法會返回全部匹配項

正則表達式和模式匹配相結合

val regex = """([0-9]+) ([a-z]+)""".r
val line = "123 abc"
line match {
//line如果符合regex1規則,會將其自動匹配成(num,str)格式
case regex(num, str) => println(num + ":" + str)
case _ => println("~~~~~~~~~`")
}

8、內部函數的定義

開發過程中,經常將各個子功能定義為一個個函數,在通過一個統一入口函數在調用這個子函數
但是這樣存在一個問題,入口函數和子函數通常是定義在一起的,既然入口函數可以被外部調用,那么子函數同樣也可以
這就不是我們想要的效果了,我們需要實現的是外部只能調用入口函數,而對于其他的子功能都是不可見的
這也就是高內聚低耦合的思想

在Scala中,函數是一等公民,意味著函數可以當做變量成員來使用
那么,在函數中可以定義變量,也就可以定義函數
這就是內部函數

def portal{//內部函數定義def action1{}def action2{}...調用內部函數action1action2
}

9、閉包

簡單的說,閉包就是指在一個函數中,能夠訪問另外一個函數的變量(必須要訪問這個變量才能完成函數的工作),讀取這個變量之后,這個函數就關閉執行,成為閉包
一個簡單的閉包例子:

//這個函數中,要完成功能必須要知道more的值
def add(more:Int) = (x:Int) => x + more
//傳入more的值為1,返回值其實還是一個函數x+1
val a = add(9)
val b = add(90)
//調用這個返回的函數,傳入x=1
a(1)
b(10)

10、高階函數

高階函數簡單的說就是 參數是函數 的函數
例如map、reduce等需要傳入匿名函數的函數
具體操作就不詳細說明了,因為高階函數太多了= =使用方法都是差不多的

11、SAM轉換

即Simple Abstract Method
在例如Java等語言中,代碼通常是這樣子寫的:

jButton.addActionListener(new ActionListener{override def actionPerformed(event:ActionEvent){counter += 1}
})

jButton的addActionListener需要一個格式為(event:ActionEvent)=>Unit的方法,上面的代碼中直接new出了一個ActionListener并重寫其方法傳入
這叫做樣本代碼,即符合這個樣本格式的方法才能使用
而很多時候,addActionListener這類的方法并不需要知道這么多信息,它只需要我們給它一個方法就行了,而不是一大堆的重新new對象,重寫方法

在Scala中是這么解決問題的:

//這是一個隱式轉換,其實起到的作用就是樣本代碼,名字任意,只要參數和返回值是符合固定格式的即可
implicit def makeAction(action:(ActionEvent) => Unit) = {new ActionListener{override def actionPerformed(event:ActionEvent){action(event)}
}//有了上面的隱式轉換,我們就可以很簡潔的直接將方法當做參數傳入
jButton.addActionListener((event:ActionEvent) => counter += 1)

此時,在這個界面的所有地方,都可以傳入(ActionEvent) => Unit類型的函數給需要的函數了

總結SAM轉換:
借助隱式轉換,將樣本代碼省去
傳入一個方法,自動掃描當前區域的隱式轉換(定義了樣本代碼),如果轉換成功就可以調用

12、Currying函數柯里化

函數的柯里化即將原來接受兩個參數的函數變成新的接受一個參數的函數的過程。
簡單的例子:

//多參數的函數
def add(x:Int,y:Int) = x + y
add(1,2)
//接受一個參數的函數
def add(x:Int) = (y:Int) => x + y
add(1)(2)

對于只接受一個參數的函數格式是不是挺熟悉的?在之前的閉包中使用的就是這種格式的函數
Scala中支持定義簡介的柯里化函數

def add(x:Int)(y:Int) = x + y

柯里化的作用有很多,其中一個就是用來做類型推斷
在一些場合,Scala編譯器可以通過第一個參數的類型推薦第二個參數的類型以便進行一些操作

13、模式匹配

Scala的模式匹配類似于switch,但是更加靈活,格式如下:

val line = ...
line match{case ... => ......case _ => ...
}

每個case都有返回值(沒有特殊指定的話)
case分支不用break
case后可以用常亮,變量,表達式,方法等

模式匹配還有很多其他的特殊的用法
例如:匹配type,array、list、tuple格式

def match_type(t:Any) = t match{case i:Int => println("Int")case s:String => println("String")case m:Map[_,_] => m.foreach(println)
}def match_array(arr:Any) = arr match{//數組中只有一個0的匹配成功case Array(0) => ...//數組中有任意的兩個數匹配成功case Array(x,y) => ...//數組中第一個為0,還有任意多個元素的匹配成功case Array(0,_*) => ...
}def match_list(lst:Any) = lst match{//List中有一個0的匹配成功(Nil表示一個空的List,::運算符是從右至左運算的,表示空List加上一個0元素,即為只有一個0的List集合)case 0 :: Nil => ...//List中有任意的兩個數匹配成功case x :: y :: Nil => ...//集合中第一個為0,還有任意多個元素的匹配成功(tail表示List中除了第一個元素外的所有元素)case 0 :: tail => ...
}

14、樣例類和樣例對象

通常在系統開發中,我們需要自己定義一些數據結構來進行統一的消息傳遞,例如經常使用的Model
在Scala中,使用樣例類和樣例對象來完成這個功能
定義的格式如下:

case class Person(...)
case object Person1(...)

15、嵌套的樣例類和模式匹配結合

abstract class Item{...}
case class Book(name:String,price:Int) extends Item
//BookList中嵌套了一個Book的樣例類
case class BookList(num:Int,books:Book*) extends Itemdef match_caseclass(item:Item) = item match{//匹配BookList,用占位符_代替的屬性都不關心,只要Book的name屬性case BookList(_,Book(name,_),_*) => ...//可以使用別名@Book的方式進行模式匹配,后面的方法體中可以使用別名直接操作case BookList(_,b1 @ Book(_,_),other @ _*) => ...
}

未完待續…

轉載于:https://www.cnblogs.com/jchubby/p/5449381.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/273151.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/273151.shtml
英文地址,請注明出處:http://en.pswp.cn/news/273151.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

maven找到mysql 連接池_在Tomcat6.0+MySQL5.0環境下配置和使用數據庫連接池

一&#xff0c;在Tomcat中配置連接池的JNDI首先到MySQL的網站上下載MySQL JDBC連接器放到%CATALINA_HOME%/lib目錄下&#xff0c;在%CATALINA_HOME%/conf目錄下找到context.xml&#xff0c;這個文件是全局的&#xff0c;如果想只對特定的應用使用可以編輯WEB-INF/context.xml文…

mysql將多個成績放在一排_mysql巧用連表查詢各科成績前三名

下列是各表的詳情&#xff0c;不想自己建表的同學可以直接copy code&#xff0c;數據隨意。創建表成績詳情表&#xff1a;CREATE TABLE score (id int(10) NOT NULL AUTO_INCREMENT,subject_id int(10) DEFAULT NULL,student_id int(10) DEFAULT NULL,score float DEFAULT NULL…

Oracle 跨庫 查詢 復制表數據 分布式查詢

方法一&#xff1a; 在眼下絕大部分數據庫有分布式查詢的須要。以下簡單的介紹怎樣在oracle中配置實現跨庫訪問。比方如今有2個數據庫服務器&#xff0c;安裝了2個數據庫。數據庫server A和B。如今來實如今A庫中訪問B的數據庫。 第一步、配置Aserver端的tnsnames.ora文件&#…

java 匹配mysql按鈕_使用Java在mysql查詢中設置匹配函數

我有以下在java中查詢(mysql)的摘錄&#xff1a;queryGeral.append("FROM product p, fabricante_product fp, fabricante f, extensao e, product_autor pa ").append(" WHERE ").append("a.nome like ? AND ").append("p.cod_material …

LeetCode Contains Duplicate (判斷重復元素)

題意&#xff1a; 如果所給序列的元素不是唯一的&#xff0c;則返回true&#xff0c;否則false。 思路&#xff1a; 哈希map解決。 1 class Solution {2 public:3 bool containsDuplicate(vector<int>& nums) {4 unordered_map<int,int> mapp;5 …

提高團隊代碼質量

近期看到一篇博客。大致的意思就是網管將原本混亂不堪的交換機整理整齊了&#xff0c;起初交換機是圖2那樣的&#xff0c;由于越來用的人越多&#xff0c;操作的人越來越多。終于成為了圖1那個樣子。這不禁讓我想到了項目中的代碼。原先在剛上線的時候談不上是完美的&#xff0…

webrender 查看是否開啟_想要體驗極致順滑的網頁加載體驗?手動開啟Firefox WebRender渲染引擎...

昨天我們提到火狐瀏覽器最新穩定版Mozilla Firefox v67 版將面向部分用戶開啟WebRender渲染引擎測試。據火狐瀏覽器團隊介紹當用戶開啟新的渲染引擎后 , 網頁加載幀率能夠從現有的 20FPS 直接提升到 60FPS。不過新的渲染引擎本身并不是用于加快網頁的加載速度&#xff0c;而是…

NOIP201307貨車運輸

試題描述A 國有n座城市&#xff0c;編號從1到n&#xff0c;城市之間有m條雙向道路。每一條道路對車輛都有重量限制&#xff0c;簡稱限重。現在有q輛貨車在運輸貨物&#xff0c;司機們想知道每輛車在不超過車輛限重的情況下&#xff0c;最多能運多重的貨物。輸入第一行有兩個用一…

knime如何連接mysql_knime怎么連接MySQL?

首先判斷一下網絡是否通&#xff1a;如果在局域網相同網段內那網絡是通的&#xff0c;不同網段間需要看是否有做隔離&#xff0c;如果沒有隔離&#xff0c;那就也是通的。測試方法可以用telnet 數據庫IP 數據庫端口號的方式探測一下 例如 telnet 192.168. 1.124 3306創建用戶&a…

Asp.net Vnext IValueProvider

概述 本文已經同步到《Asp.net Vnext 系列教程 》中] IValueProvider 根據ValueProvider獲取數據&#xff0c;在對數據進行綁定 代碼實現 private class CustomValueProvider : IValueProvider{//判斷否具有指定的前綴public Task<bool> ContainsPrefixAsync(string pref…

ECNUOJ 2615 會議安排

會議安排 Time Limit:1000MS Memory Limit:65536KBTotal Submit:451 Accepted:102 Description 科研人員與相關領域的國內外同行進行適時的接觸與充分的交流&#xff0c;對于促進提高他們的科研業務水平&#xff0c;并及時掌握科研動態是十分必要而且重要的。ECNU為了走在科技…

Kafka架構設計:分布式發布訂閱消息系統

【http://www.oschina.net/translate/kafka-design】&#xff08;較長&#xff1a;很詳細的講解&#xff09; 【我們為什么要搭建該系統】用作LinkedIn的活動流&#xff08;activity stream&#xff09;和運營數據處理管道&#xff08;pipeline&#xff09;的基礎。作為多種類型…

拼團php開發邏輯思維羅振宇_2019羅胖羅振宇跨年演講手動整理稿,看了兩遍

2019羅胖羅振宇跨年演講看了兩遍&#xff0c;手動整理文檔1.歲月不饒人&#xff0c;我們也沒饒了歲月2.你有你的計劃&#xff0c;原來這個世界另有計劃&#xff0c;既然這個世界另有計劃&#xff0c;我們就得重做計劃3.做事的人和不做事的人4.宏觀是我們必須忍受的&#xff0c;…

URLConnection

轉載&#xff08;http://www.cnblogs.com/shyang--TechBlogs/archive/2011/03/21/1990525.html&#xff09; 關于URLConnection&#xff0c;網上很多回答都是對API的翻譯&#xff0c;很崩潰&#xff0c;我是看了很多之后&#xff0c;然后看API才發現的。此后我會吸取教訓&#…

java文件拷貝_Java實現文件拷貝的4種方法

第一種方法:古老的方式public static long forJava(File f1,File f2) throws Exception{long timenew Date().getTime();int length2097152;FileInputStream innew FileInputStream(f1);FileOutputStream outnew FileOutputStream(f2);byte[] buffernew byte[length];while(tru…

今夜的硬件之旅

6腳繼電器&#xff1a; 匯科繼電器HK4100F-DC6V-SHG ①3A觸點切換能力 ②具有一組常開&#xff0c;一組轉換觸點形式 ③超小型&#xff0c;標準印刷制版引出腳 ④有塑封型 Outline&#xff08;L*W*H&#xff09;外形尺寸&#xff1a;15.510.511.8 Contact Date觸電形式&#…

mp3 pcm java_Java mp3文件轉pcm文件

Java mp3文件轉pcm文件package cn.zpy.util;import java.io.File;import java.io.IOException;import javax.sound.sampled.AudioFileFormat;import javax.sound.sampled.AudioFormat;import javax.sound.sampled.AudioInputStream;import javax.sound.sampled.AudioSystem;imp…

有1~5000一組亂序數列,請使用偽代碼對該數進行排列

先把1-5000組成一個數組 冒泡排序法 $arrarray(1,2,3,4,5,6,7,8,9.....5000); $totalcount($arr); For($i0;$i<$total;$i){ For($j0;$j<$total-1;$j){ If($arr[$j]>$arr[$j1]){ $tmp$arr[$i]; $arr[$j]$arr[$j1]; $arr[$j1]$tmp; } } } 快速排序法 $arrarray(1,2,3,4,…

java 類型轉換方法_java數據類型轉換的常見方法

public class Testfun {public static void main(String[] args) {// (一)跨Number父類的類型轉換// 1、str轉int > Integer.parseInt(s1)String s1 "19";int i2 Integer.parseInt(s1);// 數字str轉化為對標的intSystem.out.println("i2" (i2));// 2…

json to java 在線_Json轉Java對象 (全網最簡版)

Json2Java(全網最簡版)json字符串轉Java對象,生成對應文件描述&特點簡易的Json轉Java工具,滿足基本日常使用(特殊需求可自行增添,代碼就一頁)在網上找了好些個這類工具,不是只暴露iead插件就是復雜&沒文檔,于是自己寫了個全網最簡版Json2Javaonly one file用法public c…