簡體   English   中英

Scala:理解參數多態性

[英]Scala: understanding parametric polymorphism

有什么區別

def drop1[A](l: List[A]) = l.tail

def drop1(l: List[Int]) = l.tail

如果用法看起來像

drop1(List(1,2,3))

應該何時使用其中一個,為什么? 雖然我能理解第二個例子,但我並不真正理解第一個例子的目的。

真的很簡單。 你的第一個例子是指泛型的概念。

泛型有一個簡單的目標,使某些方法通用 ,例如非類型依賴。

讓我們看看這個簡單的例子。 假設我想為List編寫drop1方法。

我可以為每種類型寫一個:(慢,重復):

def drop1(l: List[Int]): List[Int] = l.tail // this only works for Int

def drop1(l: List[String]): List[String] = l.tail // this only works for String 

您可以看到如何為每種類型編寫上述內容。 為了克服這個問題,你有一些泛型:

def drop1[A](l: List[A]): List[A] = l.tail // this works for any given type.

基本上說:無論List中包含什么類型,給我尾巴。 而不是為幾乎無限數量的類型編寫成千上萬的drop1變體,我只需要編寫一個。

現在在Scala中,您的實現最好用以下方法完成:

implicit class ListOps[A](val l: List[A]) extends AnyVal {
   def drop1: List[A] = l match {
     case head :: tail => tail
     case Nil => Nil
   }
}
// you can now have
List(1, 2, 3).drop1

重命名眾所周知的庫方法通常也是一個壞主意。 tail操作不安全, drop是安全的。 所有你造成的都是混亂,因為有一個默認的drop方法。

List(1, 2, 3) drop 1

簡而言之 - 一些操作不依賴於特定類型並且可以被抽象。 計算蘋果和計算橙子基本上是相同的操作。 如果你要重用算法,那么抽象一些類型而不是寫作更聰明

def countOranges(xs: List[Orange]) = { some code } 
def countApples(xs: List[Apple]) = { the very same code }

我遲到了,如果你對Java中的泛型有了一個想法,那么可以在這里進行類比: -

Java - >泛型類的對象可以在方法參數中傳遞。

class Test<T> {
    // An object of type T is declared
    T obj;
    Test(T obj) {  this.obj = obj;  }  // constructor
    // some other methods in class 
}

Test<String> testobj = new Test<String>();

public void function(testobj){ 
// do something with testobj 
}

Scala - >通用參數函數在scala中的工作方式相同。 這里,[A]定義了scala中的泛型Type

def drop1[A](l: List[A]) = l.tail

使用上述功能: -

scala>drop1(List(1,2,3))   // output List(2, 3)
scala>drop1(List(1.0,2.0,3.0)) // output List(2.0, 3.0)
scala>drop1(List('a','b','c'))  // output List(b, c)

說明: - 只需傳遞任何類型的List,它就像魅力一樣。語法如下: -

def function[Type](param:Type):Type = {do something}
//snippet to explain scala parametric polymorphism

object MethodParametricPolymorphism {
  //parametric polymorphism is similar/same as of java generics
  def countOranges(oranges : List[Orange]) = oranges.size;
  def countApples(apples : List[Apple]) = apples.size
  //if algo is same then paramatric polymorphism can be used
  def count[A](items : List[A]) = items.size

  val oranges : List[Orange] =  List( new Orange(1.1))
  val apples : List[Apple] =  List( new Apple(2.1), new Apple(2.2))

  countOranges(oranges);
  countApples(apples);
  //using polymorphic typed method
  count(oranges);
  count(apples);

  case class Orange ( weight: Double)
  case class Apple ( weight: Double)
 }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM