动态

详情 返回 返回

Scala-泛型 - 动态 详情

泛型

泛型定義

Scala的泛型和Java中的泛型表達的含義都是一樣的,對處理的數據類型進行約束,但是Scala提供了更加強大的功能

  • scala中的泛型採用中括號

  • scala中的泛型是不可變的

  • 泛型和類型不是一個層面的東西

    所以scala中泛型和類型無法聯合使用

泛型語法

如果能將類型和泛型當成一個整體來使用的話,那不就方便了嗎?

  • 如果將類型和泛型聯合使用,那麼類型相同時,如果泛型存在父子類關係,那麼聯合的類型也就存在父子類關係,這個操作其實就是一種變化,稱之為協變, +T

  • 如果類型相同,泛型之間存在父子關係,那麼讓聯合後的類型存在子父關係。這個操作其實也是一種變化,稱之為逆變, -T

val message1 : Message[Child] = new Message[Child]()
val message2 : Message[Child] = new Message[Parent]()
//val message3 : Message[Child] = new Message[SubChild]()  -- 不符合新的父子關係
// Child(父) -> child -> SubChild(子)
// MessageChild(子)         MessageSubChild(父)

// Child(子)             Parent(父)
// MessageChild(父)      MessageParent(子)
class Message[-T] {}
class Parent {}
class Child extends Parent {}
class SubChild extends Child {}

泛型和類型的區別

  • 所謂的類型,其實就是對外部的數據做約束
  • 所謂的泛型,其實就是對內部的數據做約束

泛型特徵

  • 泛型和類型的層次不一樣。不能作為整體來考慮

  • 泛型在某些場合中,其實就是類型參數,用於向類中傳遞參數

            Test<User> userTest = new Test<User>();
            final User t = userTest.t;
    
            Test userTest1 = new Test();
            final Object t1 = userTest1.t;
    
  • 泛型其實只在編譯時有效, 將這個操作稱之為"泛型擦除"

            Test<User> userTest = new Test<User>();
            userTest.t = new Emp();  //--> error
            System.out.println(userTest);
    
  • 泛型主要目的是為了約束內部數據的類型

            List list = new ArrayList();
            list.add(new Emp());
            List<User> userList = list;
            // System.out.println(userList);
            for ( User user : userList ) {}
    
  • 泛型和類型不是一個層次,泛型沒有所謂的父子關係

    public static void main(String[] args) {
        List<String> stringList = new ArrayList<String>();
        test(stringList); //--> error
    
        List<Object> stringList1 = new ArrayList<Object>();
        test(stringList1);
    }
    public static void test( Collection<Object> list ) {
        System.out.println(list);
    }
    
  • 泛型的不可變

        public static void main(String[] args) {
    
            // TODO 6. 泛型的不可變
            List<Child> childList = new ArrayList<Child>(); //--> error
            List<Child> childList1 = new ArrayList<Parent>(); //--> error
            List<Child> childList2 = new ArrayList<SubChild>();
        }
        }
        class Parent {
    
        }
        class Child extends Parent {
    
        }
        class SubChild extends Child {
    
        }
    
  • 為了使用方便,可以定義泛型的邊界

    public static void main(String[] args) {
        Producer<Child> p = new Producer<Child>();
        
        p.produce(new Message<Child>());
        p.produce(new Message<Parent>());
        p.produce(new Message<SubChild>());  //--> error
    
        Consumer<Child> c = new Consumer<Child>();
        final Message<? extends Child> message = c.getMessage();
        final Child data = message.data;
    }
    
    class Message<T> {
        public T data;
    }
    
    
    // 分別給消費者和生產者設置上限與下限
    class Producer<A> {
        public void produce( Message<? super A> message ) {
    
        }
    }
    
    class Consumer<B> {
        public Message<? extends B> getMessage() {
            return null;
        }
    }
    

泛型的上限與下限

Scala的泛型可以根據功能設定類樹的邊界

這裏的上限和下限採用的是顏文字

    def main(args: Array[String]): Unit = {
        val p = new Producer[Child]
        p.produce(new Message[Child])
        p.produce(new Message[Parent])
        p.produce(new Message[SubChild]) // --> error

        val c = new Consumer[Child]
        val m: Message[_ <: Child] = c.consume()
        val data: Child = m.data
    }
    class Message[T] {
        var data : T = _
    }
    class Parent {}

    class Child extends Parent {}

    class SubChild extends Child {}

// 設置上限與下限
    class Producer[T] {
        def produce( message : Message[_ >: T] ): Unit = {

        }
    }
    class Consumer[T] {
        def consume(): Message[_ <: T] = {
            null
        }
    }

集合的泛型

使用時需甄別源碼 看是否有上限下限

def main(args: Array[String]): Unit = {
        val list : List[Child] = List(
            new Child(), new Child(), new Child()
        )
    // 集合中函數要遵守繼承
    	list.fold[Parent](new Parent)(
            (x,y) => x
        )
    
    // 但left不需要考慮繼承
        list.foldLeft[SubChild](new SubChild)((x, y) => x)
    }
class Parent {}
class Child extends Parent {}
class SubChild extends Child {}

上下文限定

上下文限定是將泛型和隱式轉換的結合產物,以下兩者功能相同,使用上下文限定[A : Ordering]之後,方法內無法使用隱式參數名調用隱式參數,需要通過implicitly[Ordering[A]]獲取隱式變量,如果此時無法查找到對應類型的隱式變量,會發生出錯誤。

object ScalaGeneric {
    def main(args: Array[String]): Unit = {
        def f[A : Test](a: A) = println(a)
        implicit val test : Test[User] = new Test[User]
        f( new User() )
    }
    class Test[T] {
    }
    class Parent {
    }
    class User extends Parent{
    }
    class SubUser extends User {
    }
}

Add a new 评论

Some HTML is okay.