1. 程式人生 > >scala習題(十)——特質

scala習題(十)——特質

重點章節,與java有著比較大的分歧,在java與scala中都僅能繼承一個基類,這麼做是為了避免菱形繼承,所以兩者都限制的很死,只能單繼承,但這樣就對類的特質化產生了障礙,而為了避免這些問題,java提供了interface,scala則提供了trait也就是特質,介面類和trait的區別在於,一個僅能提供抽象的方法,且不能包含具體實現方法和欄位,而在trait中則沒有這個限制,trait與scala中類的區別只有一點,就是沒有帶引數的建構函式

一、java.awt.Rectangle類有兩個很好用的方法translate和grow,但可惜的是像java.awt.geom.Eclipse2D這樣的類中沒有。在scala中,你可以解決掉這個問題。定義一個RectangleLike特質,加入具體的translate和grow方法,提供任何你需要用來實現的方法,即便你可以像如下的程式碼這樣混入特質

val egg=new java.awt.geom.Eclipse2D.Double(5,10,20,30) with RectangleLike
egg.translate(10,-10)
egg.groww(10,20)
  trait RectangleLike {
  //自身型別代表只能混入eclipse2d類
    this:java.awt.geom.Ellipse2D.Double=>
    def translate(x:Int,y:Int):Unit={
      this.x=x;
      this.y=y;
    }
    def grow(x:Int,y:Int){
      this
.x=x; this.y=y; } }

2.通過把scala.math.Ordered[Point]混入java.awt.Point的方式,定義OrdererPoint類,按辭典編輯方式排序,也就是說,如果x

import java.awt.Point;
class OrderPoint extends Point with scala.math.Ordered[Point]{
def compare(that :Point):Int={
if(this.x

3.檢視bitset類,將它的所有超類和特質繪製成一張圖,忽略型別引數([….)中的所有內容,然後給出改特質的線性化規格內容

trait BitSet extends SortedSet[Int] with BitSetLike[BitSet]
繼承自SortedSet類和BitSetLike特質,具體內容可以去scaladoc中看

4.提供一個CryptoLogger類,將日誌資訊以凱撒密碼加密,預設情況下金鑰為3,不過使用者也可以重寫它,提供預設金鑰為3和-3作為金鑰時的使用示例
凱撒密碼就是原有字元基礎上+上偏移量來達成,容錯方面,下面不做深入

  trait logger{
    def printlog(content:String,key:Int = 3):String   
  }
  class CryptoLogger extends logger{
     def printlog(content:String,key:Int = 3):String={
       val s=for(i<- content) yield {
          (i+key).toChar;

       }
       s;
     }
  }

5.
這裡寫圖片描述

在scala中雖然特質的混入沒有任何限制,但需要注意,如果特質繼承自類,則只能混入繼承該類的類裡面,否則會像下面的列子裡一樣報錯

scala> class Foo
defined class Foo

scala> trait FooTrait extends Foo
defined trait FooTrait

scala> val good = new Foo with FooTrait
good: Foo with FooTrait = $anon$1@773d3f62

scala> class Bar
defined class Bar

scala> val bad = new Bar with FooTrait
<console>:10: error: illegal inheritance; superclass Bar
 is not a subclass of the superclass Foo
 of the mixin trait FooTrait
       val bad = new Bar with FooTrait

//題解只能是這樣
//自己實現propertyChangeSupport的特質,然後混入java.Point,直接繼承必然會報錯
trait propertyChange //自己實現
val p=new Point() with propertyChange;//混入特質

6.因為java中只可以單繼承,所以jcontainer不能夠直接繼承Container和jcomponent,scala中可以通過特質來實現

7.寫一個展現特質的類

  class animal{
    val animalname:String="animal";

  }
  trait  predation{
     val animalname:String;
    def predation(s:String){
       println(animalname+" is prey on "+s);
    }
  }
  trait feed{
     val animalname:String;
    def feed(){
      println(animalname+" is feed by people");
    }
  }
  class cat extends {override val animalname="cat"} with animal with feed with predation{


  }

8.在javaio類庫中,你可以通過BufferInputStream修飾器來給輸入流增加緩衝機制,用特質來重寫緩衝,簡單起見,重寫read方法

檢視java.io的原始碼,如果沒有可以使用jui來反編譯一下,之後將原始碼複製過來注意好特質的特點,不能有含有引數的構造器即可,之後補上

9.使用本章的日誌生成器特質,給前一個練習中的方案增加日誌功能,要求體現出緩衝的效果

檢視java.io的原始碼,如果沒有可以使用jui來反編譯一下,之後將原始碼複製過來注意好特質的特點,不能有含有引數的構造器即可,之後補上

10.實現一個iterableInputStream類,擴充套件java.io.inputStream並混入iterable[byte]特質

  class IterableInputStream extends InputStream with Iterable[Byte]{
    override def read():Int={
      return 1;
    }
    override def iterator: Iterator[Byte]=null;
  }