2013-08-12 2 views
0

Редактировать Упрощенный пример. Добавлено больше деталей.Как использовать вложенные дженерики в scala

Что я хочу сделать, это составить класс с помощью метода. Класс имеет параметр типа A [B], где A и B - абстрактные типы (общие параметры), а его методы могут работать с объектами типов A или B или другими типами, состоящими из A или B. Например , класс может иметь метод, который принимает объект типа A [B] как параметр и возвращает объект типа B.

Этот тип шаблона чрезвычайно распространен в стандартной библиотеке шаблонов C++.

Возможно ли это в scala?

В моем примере ниже, в ListDoer, A является абстрактным именем типа ListT и B абстрактным текстовым элементом TElement. Позже, я стараюсь предоставить конкретные типы, ListT [TElement] = MyList [Double]

class ListDoer[ ListT[TElement] ] 
{ 
    // Processes abstract list type.     
    def doIt(list:ListT[TElement]) : TElement = { list.get(0) } // TElement not found 

    // Attempt 2: 
    type L=ListT[TElement]    // TElement not found 
    def doIt2(list:L) : TElement ={ list.get(0) } // TElement not found 
} 

// More concrete list type 
class MyList[TElement] 
{ 
    var None: TElement = _       
    def get(i:Int): TElement = None // placeholder    
    def put(i:Int, value:TElement): Unit = { } 
} 

// MyList[Double] is the concrete list type that doIt should take as a parameter 
val doer2 = new ListDoer[ MyList[Double] ] // MyList[Double] takes no parameters, expected one 

val list1 = new MyList[Double] 
doer2.doIt(list1)   // Process list1. Should return list1.get(0) 

list.get (0) является реализацией заполнителя для этого примера.

Класс ListDoer не должен содержать любые внешние типы, кроме указанных в качестве параметров типа. (например, он не должен привязываться к конкретной реализации списка или интерфейсов, указанных в какой-либо конкретной библиотеке коллекций). Однако приведенный выше код потребует, чтобы у ListT [ElementT] был метод: get (Int): ElementT и заставить экземпляр ListDoer не создаваться, это не выполняется.

Приведенный выше код выглядит разумным для меня (Исходя из фона C++), но не в состоянии собрать в двух местах:

  • Скала не может видеть имя TElement в любом месте в пределах ListDoer. Это делает его трудно сделать методы, которые принимают или возвращают TElement

  • ListDoer не может быть создан

Этом этот видом вложенного использования дженерик разрешенных в Скале?

+0

Если вы расскажете, с какими проблемами вы сталкиваетесь, и что вы хотите от этого кода, возможно, кто-то сможет вам помочь. – pedrofurla

+2

Это очень неопределенный вопрос, не особо мешающий цели, что очень затрудняет ответ. – MushinNoShin

+0

Спасибо, принесли вопрос. Более детально. – user48956

ответ

2
object XXX { 

    class MyList[T] { 
      var None: T = _ 
      def get(k: Int): T = None // placeholder    
      def put(k: Int, v: T): Unit = {} 
    } 

    class ListDoer[T] { 

      // this defines the "wrapper" type 
      // which requires only get method to be there 
      type W[T] = { def get(k: Int): T } 

      def doIt(list: W[T]): T = { 
       return null.asInstanceOf[T] 
      } 
    } 

    type L = Double 
    val doer1 = new ListDoer[L] // L takes no parameters, expected one 
    val doer2 = new ListDoer[Double] // L takes no parameters, expected one 

    val list1 = new MyList[Double] 
    val list2 = List[L]() 
    doer1.doIt(list1) 

} 
+0

В этом случае ListDoer имеет ограничение, что doIt принимает только объекты типов T. Нельзя ли сделать его более общим, чтобы он принимал типы формы A [B]? – user48956

+0

Извините, только что реализованный последний комментарий был неправильным. В вашем решении ListDoer требует List [T]. То, что я хотел бы сделать, это A [B], где A = type {get (Int): B} - то есть A - ЛЮБЫЙ тип, имеющий метод get (Int): B. – user48956

+0

Ознакомьтесь с обновленным ответом выше –

Смежные вопросы