<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                課程內容: [TOC=2,2] ## 視界(“類型類”) 有時候,你并不需要指定一個類型是等/子/超于另一個類,你可以通過轉換這個類來偽裝這種關聯關系。一個視界指定一個類型可以被“看作是”另一個類型。這對對象的只讀操作是很有用的。 **隱**?函數允許類型自動轉換。更確切地說,在隱式函數可以幫助滿足類型推斷時,它們允許按需的函數應用。例如: ~~~ scala> implicit def strToInt(x: String) = x.toInt strToInt: (x: String)Int scala> "123" res0: java.lang.String = 123 scala> val y: Int = "123" y: Int = 123 scala> math.max("123", 111) res1: Int = 123 ~~~ 視界,就像類型邊界,要求對給定的類型存在這樣一個函數。您可以使用`<%`指定類型限制,例如: ~~~ scala> class Container[A <% Int] { def addIt(x: A) = 123 + x } defined class Container ~~~ 這是說?**A**?必須“可被視”為?**Int**?。讓我們試試。 ~~~ scala> (new Container[String]).addIt("123") res11: Int = 246 scala> (new Container[Int]).addIt(123) res12: Int = 246 scala> (new Container[Float]).addIt(123.2F) <console>:8: error: could not find implicit value for evidence parameter of type (Float) => Int (new Container[Float]).addIt(123.2) ^ ~~~ ## 其他類型限制 方法可以通過隱含參數執行更復雜的類型限制。例如,`List`支持對數字內容執行`sum`,但對其他內容卻不行。可是Scala的數字類型并不都共享一個超類,所以我們不能使用`T <: Number`。相反,要使之能工作,Scala的math庫[對適當的類型T 定義了一個隱含的`Numeric[T]`](http://www.azavea.com/blogs/labs/2011/06/scalas-numeric-type-class-pt-1/)。 然后在`List`定義中使用它: ~~~ sum[B >: A](implicit num: Numeric[B]): B ~~~ 如果你調用`List(1,2).sum()`,你并不需要傳入一個?*num*?參數;它是隱式設置的。但如果你調用`List("whoop").sum()`,它會抱怨無法設置`num`。 在沒有設定陌生的對象為`Numeric`的時候,方法可能會要求某種特定類型的“證據”。這時可以使用以下類型-關系運算符: | A =:= B | A 必須和 B相等 | | A <:< B | A 必須是 B的子類 | | A <%< B | A 必須可以被看做是 B | ~~~ scala> class Container[A](value: A) { def addIt(implicit evidence: A =:= Int) = 123 + value } defined class Container scala> (new Container(123)).addIt res11: Int = 246 scala> (new Container("123")).addIt <console>:10: error: could not find implicit value for parameter evidence: =:=[java.lang.String,Int] ~~~ 類似地,根據之前的隱式轉換,我們可以放松約束為可視性: ~~~ scala> class Container[A](value: A) { def addIt(implicit evidence: A <%< Int) = 123 + value } defined class Container scala> (new Container("123")).addIt res15: Int = 246 ~~~ ### 使用視圖進行泛型編程 在Scala標準庫中,視圖主要用于實現集合的通用函數。例如“min”函數(在?**Seq[]**?上)就使用了這種技術: ~~~ def min[B >: A](implicit cmp: Ordering[B]): A = { if (isEmpty) throw new UnsupportedOperationException("empty.min") reduceLeft((x, y) => if (cmp.lteq(x, y)) x else y) } ~~~ 其主要優點是: * 集合中的元素并不是必須實現?**Ordered**?特質,但?**Ordered**?的使用仍然可以執行靜態類型檢查。 * 無需任何額外的庫支持,你也可以定義自己的排序: ~~~ scala> List(1,2,3,4).min res0: Int = 1 scala> List(1,2,3,4).min(new Ordering[Int] { def compare(a: Int, b: Int) = b compare a }) res3: Int = 4 ~~~ 作為旁注,標準庫中有視圖來將?**Ordered**?轉換為?**Ordering**?(反之亦然)。 ~~~ trait LowPriorityOrderingImplicits { implicit def ordered[A <: Ordered[A]]: Ordering[A] = new Ordering[A] { def compare(x: A, y: A) = x.compare(y) } } ~~~ #### 上下文邊界和implicitly[] Scala2.8引入了一種串聯和訪問隱式參數的快捷方式。 ~~~ scala> def foo[A](implicit x: Ordered[A]) {} foo: [A](implicit x: Ordered[A])Unit scala> def foo[A : Ordered] {} foo: [A](implicit evidence$1: Ordered[A])Unit ~~~ 隱式值可能會通過?**implicitly**?被訪問 ~~~ scala> implicitly[Ordering[Int]] res37: Ordering[Int] = scala.math.Ordering$Int$@3a9291cf ~~~ 相結合后往往會使用更少的代碼,尤其是串聯視圖的時候。 ## 更高級多態性類型 和 特設多態性 Scala可以對“更高階”的類型進行抽象。例如,假設您需要用幾種類型的容器處理幾種類型的數據。你可能定義了一個`Container`的接口,它可以被實現為幾種類型的容器:`Option`、`List`等。你要定義可以使用這些容器里的值的接口,但不想確定值的類型。 這類似與函數柯里化。例如,盡管“一元類型”有類似`List[A]`的構造函數,這意味著我們必須滿足一個“級別”的類型變量來產生一個具體的類型(就像一個沒有柯里化的函數需要只提供一個參數列表來被調用),更高階的類型需要更多。 ~~~ scala> trait Container[M[_]] { def put[A](x: A): M[A]; def get[A](m: M[A]): A } scala> val container = new Container[List] { def put[A](x: A) = List(x); def get[A](m: List[A]) = m.head } container: java.lang.Object with Container[List] = $anon$1@7c8e3f75 scala> container.put("hey") res24: List[java.lang.String] = List(hey) scala> container.put(123) res25: List[Int] = List(123) ~~~ 注意:*Container*是參數化類型的多態(“容器類型”)。 如果我們結合隱式轉換implicits使用容器,我們會得到“特設的”多態性:即對容器寫泛型函數的能力。 ~~~ scala> trait Container[M[_]] { def put[A](x: A): M[A]; def get[A](m: M[A]): A } scala> implicit val listContainer = new Container[List] { def put[A](x: A) = List(x); def get[A](m: List[A]) = m.head } scala> implicit val optionContainer = new Container[Some] { def put[A](x: A) = Some(x); def get[A](m: Some[A]) = m.get } scala> def tupleize[M[_]: Container, A, B](fst: M[A], snd: M[B]) = { | val c = implicitly[Container[M]] | c.put(c.get(fst), c.get(snd)) | } tupleize: [M[_],A,B](fst: M[A],snd: M[B])(implicit evidence$1: Container[M])M[(A, B)] scala> tupleize(Some(1), Some(2)) res33: Some[(Int, Int)] = Some((1,2)) scala> tupleize(List(1), List(2)) res34: List[(Int, Int)] = List((1,2)) ~~~ ## F-界多態性 通常有必要來訪問一個(泛型)特質的具體子類。例如,想象你有一些泛型特質,但需要可以與它的某一子類進行比較。 ~~~ trait Container extends Ordered[Container] ~~~ 然而,現在比較方法是必須的了 ~~~ def compare(that: Container): Int ~~~ 因此,我們不能訪問具體子類型,例如: ~~~ class MyContainer extends Container { def compare(that: MyContainer): Int } ~~~ 編譯失敗,因為我們對?**Container**?指定了Ordered特質,而不是對特定子類型指定的。 為了調和這一點,我們改用F-界的多態性。 ~~~ trait Container[A <: Container[A]] extends Ordered[A] ~~~ 奇怪的類型!但可以看到怎樣對?**A**?實現了Ordered參數化,它本身就是?**Container[A]** 所以,現在 ~~~ class MyContainer extends Container[MyContainer] { def compare(that: MyContainer) = 0 } ~~~ 他們是有序的了: ~~~ scala> List(new MyContainer, new MyContainer, new MyContainer) res3: List[MyContainer] = List(MyContainer@30f02a6d, MyContainer@67717334, MyContainer@49428ffa) scala> List(new MyContainer, new MyContainer, new MyContainer).min res4: MyContainer = MyContainer@33dfeb30 ~~~ 鑒于他們都是?**Container[_]**?的子類型,我們可以定義另一個子類并創建?**Container[_]**?的一個混合列表: ~~~ scala> class YourContainer extends Container[YourContainer] { def compare(that: YourContainer) = 0 } defined class YourContainer scala> List(new MyContainer, new MyContainer, new MyContainer, new YourContainer) res2: List[Container[_ >: YourContainer with MyContainer <: Container[_ >: YourContainer with MyContainer <: ScalaObject]]] = List(MyContainer@3be5d207, MyContainer@6d3fe849, MyContainer@7eab48a7, YourContainer@1f2f0ce9) ~~~ 注意結果類型是怎樣成為?**YourContainer 和 MyContainer**?類型確定的下界。這是類型推斷的工作。有趣的是,這種類型甚至不需要是有意義的,它只是提供了一個合乎邏輯的最大下界為列表的統一類型。如果現在我們嘗試使用?**Ordered**?會發生什么? ~~~ (new MyContainer, new MyContainer, new MyContainer, new YourContainer).min <console>:9: error: could not find implicit value for parameter cmp: Ordering[Container[_ >: YourContainer with MyContainer <: Container[_ >: YourContainer with MyContainer <: ScalaObject]]] ~~~ 對統一的類型?**Ordered[]**不存在了。太糟糕了。 ## 結構類型 Scala 支持?**結構類型 structural types**?— 類型需求由接口?*構造*?表示,而不是由具體的類型表示。 ~~~ scala> def foo(x: { def get: Int }) = 123 + x.get foo: (x: AnyRef{def get: Int})Int scala> foo(new { def get = 10 }) res0: Int = 133 ~~~ 這可能在很多場景都是相當不錯的,但這個實現中使用了反射,所以要注意性能! ## 抽象類型成員 在特質中,你可以讓類型成員保持抽象。 ~~~ scala> trait Foo { type A; val x: A; def getX: A = x } defined trait Foo scala> (new Foo { type A = Int; val x = 123 }).getX res3: Int = 123 scala> (new Foo { type A = String; val x = "hey" }).getX res4: java.lang.String = hey ~~~ 在做依賴注入等情況下,這往往是一個有用的技巧。 您可以使用hash操作符來引用一個抽象類型的變量: ~~~ scala> trait Foo[M[_]] { type t[A] = M[A] } defined trait Foo scala> val x: Foo[List]#t[Int] = List(1) x: List[Int] = List(1) ~~~ ## 類型擦除和清單 正如我們所知道的,類型信息在編譯的時候會因為?*擦除*?而丟失。 Scala的?**清單(Manifests)**?功能,使我們能夠選擇性地恢復類型信息。清單提供了一個隱含值,根據需要由編譯器生成。 ~~~ scala> class MakeFoo[A](implicit manifest: Manifest[A]) { def make: A = manifest.erasure.newInstance.asInstanceOf[A] } scala> (new MakeFoo[String]).make res10: String = "" ~~~ ## 案例分析: Finagle 參見: https://github.com/twitter/finagle ~~~ trait Service[-Req, +Rep] extends (Req => Future[Rep]) trait Filter[-ReqIn, +RepOut, +ReqOut, -RepIn] extends ((ReqIn, Service[ReqOut, RepIn]) => Future[RepOut]) { def andThen[Req2, Rep2](next: Filter[ReqOut, RepIn, Req2, Rep2]) = new Filter[ReqIn, RepOut, Req2, Rep2] { def apply(request: ReqIn, service: Service[Req2, Rep2]) = { Filter.this.apply(request, new Service[ReqOut, RepIn] { def apply(request: ReqOut): Future[RepIn] = next(request, service) override def release() = service.release() override def isAvailable = service.isAvailable }) } } def andThen(service: Service[ReqOut, RepIn]) = new Service[ReqIn, RepOut] { private[this] val refcounted = new RefcountedService(service) def apply(request: ReqIn) = Filter.this.apply(request, refcounted) override def release() = refcounted.release() override def isAvailable = refcounted.isAvailable } } ~~~ 一個服務可以通過過濾器對請求進行身份驗證。 ~~~ trait RequestWithCredentials extends Request { def credentials: Credentials } class CredentialsFilter(credentialsParser: CredentialsParser) extends Filter[Request, Response, RequestWithCredentials, Response] { def apply(request: Request, service: Service[RequestWithCredentials, Response]): Future[Response] = { val requestWithCredentials = new RequestWrapper with RequestWithCredentials { val underlying = request val credentials = credentialsParser(request) getOrElse NullCredentials } service(requestWithCredentials) } } ~~~ 注意底層服務是如何需要對請求進行身份驗證的,而且還是靜態驗證。因此,過濾器可以被看作是服務轉換器。 許多過濾器可以被組合在一起: ~~~ val upFilter = logTransaction andThen handleExceptions andThen extractCredentials andThen homeUser andThen authenticate andThen route ~~~ 享用安全的類型吧! Built at?[@twitter](http://twitter.com/twitter)?by?[@stevej](http://twitter.com/stevej),?[@marius](http://twitter.com/marius), and?[@lahosken](http://twitter.com/lahosken)?with much help from?[@evanm](http://twitter.com/evanm),?[@sprsquish](http://twitter.com/sprsquish),?[@kevino](http://twitter.com/kevino),?[@zuercher](http://twitter.com/zuercher),?[@timtrueman](http://twitter.com/timtrueman),?[@wickman](http://twitter.com/wickman), and[@mccv](http://twitter.com/mccv); Russian translation by?[appigram](https://github.com/appigram); Chinese simple translation by?[jasonqu](https://github.com/jasonqu); Korean translation by?[enshahar](https://github.com/enshahar); Licensed under the?[Apache License v2.0](http://www.apache.org/licenses/LICENSE-2.0).
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看