2016-12-11 8 views
2

周りの挙動を一般化するためにどのように私は、彼らがどのinterfaceabstractまたは任意の他のクラスによって関連していない(私は変更することになっていない午前三部品ライブラリからの)2つのJavaクラスFooBarを持っています。用Scalaは:無関係なJavaクラス

しかしそれらは

public String createToken(String id)両方のクラスに同じである

、リストに返されるオブジェクトの種類は別に非常に似ている他の方法のような署名方法を有します=>public List[FooItem] getItems(String id)

とクラスBar =>public List[BarItem] getItems(String id)

のクラス

私のScalaコードでは、基本的に複製されたメソッドでこれら2つのクラスを使用しています。たとえば:あなたは、コードを見ることができるように

def getFooItems(foo: Foo, id: String): Vector[FooItem] = { 
    foo.createToken(id) 
    foo.getItems(id).asScala.toVector 
} 

def getBarItems(bar:Bar, id: String): Vector[BarItem] = { 
    bar.createToken(id) 
    bar.getItems(id).asScala.toVector 
} 

はほとんど同じですが、方法(とちょうど2つのクラス以上)の多くのためにそれは巨大な重複コードのかなりの一種になります。

def getItems[A,B](someClass:A, id: String): Vector[B] = { 
    someClass.createToken(id) 
    someClass.getItems(id).asScala.toVector 
} 

それとも唯一の方法を入力アヒル:

の並べ替えを取得するためのコードを一般化するスカラ座での方法はありますか?

答えて

3

お試しになることをお勧めします。typeclass patternあなたはFooBarのための共通のインタフェースを定義する必要があり

まず:

object FooBar { 
    class Foo { 
    def createToken(id: String): String = ??? 
    def getItems(id: String): List[FooItem] = ??? 
    } 
    class Bar { 
    def createToken(id: String): String = ??? 
    def getItems(id: String): List[BarItem] = ??? 
    } 

    class FooItem 
    class BarItem 

    implicit object FooTokenable extends Tokenable[Foo, FooItem] { 
    def createToken(f: Foo, id: String) = f.createToken(id) 
    def getItems(f: Foo, id: String) = f.getItems(id) 
    } 

    implicit object BarTokenable extends Tokenable[Bar, BarItem] { 
    def createToken(b: Bar, id: String) = b.createToken(id) 
    def getItems(b: Bar, id: String) = b.getItems(id) 
    } 
} 

今、あなたは使用することができます。

trait Tokenable[T, TItem] { 
    def createToken(t: T, id: String): String 
    def getItems(t: T, id: String): List[TItem] 
} 

を次に、あなたがそれを適用するすべてのクラスの実装を定義する必要があります暗黙的なTokenableパラメータを持つ任意の方法で:

import FooBar._ 

def getItemsAsVector[T, TItem](t: T, id: String) 
    (implicit tok: Tokenable[T, TItem]) = { 
    tok.createToken(t, id) 
    tok.getItems(t, id).toVector 
} 

val vector = getItemsAsVector(new Foo, "my_id") 
+0

興味深い提案ですが、私は具体的な見通しを見ません。つまり、あなたはファサードを持つ余分な間接指示でこのようにすることができますが、クラスごとにすべてのメソッドを「繰り返す」必要があります。クラスやメソッドがたくさんある場合は苦痛です。 – Randomize

+1

はい、 'Foo'や' Bar'のようにクラスごとに1回だけすると、 'getItemsAsVector'のような' Tokenable'を使うメソッドごとに自分自身を繰り返す必要はありません。とにかくあらゆるタイプの具体的な方法を指摘する必要があるので、それほど作業を減らすことはできません。 – adamwy

関連する問題