11

play2/slick2 プロジェクトの抽象的な CRUD-DAO に取り組んでいます。便利なタイプ セーフなプライマリ ID を持つために、スリック&の上に追加の抽象化と利便性としてUnicornを使用しています。MappedToColumnBaseType

Unicorn は基本的な CRUD-DAO クラスBaseIdRepositoryを提供しており、これをプロジェクト固有のニーズに合わせてさらに拡張したいと考えています。クラスの署名は

class BaseIdRepository[I <: BaseId, A <: WithId[I], T <: IdTable[I, A]]
  (tableName: String, val query: TableQuery[T])
  (implicit val mapping: BaseColumnType[I])
  extends BaseIdQueries[I, A, T]

これにより、DAO の実装は次のようになります。

class UserDao extends 
  BaseIdRepository[UserId, User, Users]("USERS", TableQuery[Users])

これは私には非常に冗長に思えます。tableNamequeryfromを提供することができT、自分の Abstract DAO に次の署名を付けました。

abstract class AbstractIdDao[I <: BaseId, A <: WithId[I], T <: IdTable[I, A]] 
  extends BaseIdRepository[I,A,T](TableQuery[T].baseTableRow.tableName, TableQuery[T])

Scala で何らかの形で型Iを推測しA、次のような署名を可能にすることは可能ですか? (Usersはクラス拡張ですIdTable)

class UserDao extends AbstractIdDao[Users]

これはランタイムリフレクションなしで可能ですか? ランタイム リフレクションのみの場合: クラス定義でマニフェストを使用するにはどうすればよいですか? また、リアクティブ アプリケーションでのパフォーマンスへの影響はどの程度ですか?

また、私はこの言語にかなり慣れていないため、自分で作業しています。これは scala での良い実践ですか?

ご協力ありがとう御座います。私の質問と英語を自由に批判してください。もちろん、改善はUnicorn git-repoに提出されます

編集: 実際には、エラークラスタイプが必要TableQuery[T].baseTableRow.tableName, TableQuery[T]であるために機能しませんが、Tが見つかりました。IDEAは表面的には問題ありませんでしたが、scalacはそうではありませんでした。

4

1 に答える 1

0

あなたの最初の質問については、Slick を使用しているときにもこれに遭遇しました。しかし、考えてみると、コンパイル時にこれを行うことができないことがわかります。これは、この型情報が必要であり、型パラメーター間の関係を指定するためです。そうしないと、次BaseIdRepositoryのような型が意味をなさないクラスを構築できます。IdTablesここで、表は投影を表していません。これらの関係のそれぞれに名前が必要なので、3 つの名前付き型パラメーターが必要です。最初のものを省略すると、Id を含むプロジェクションなしで IdRepository を構築できます。2 番目のものを省略すると、ID 列のないテーブルを持つことができます。3 番目のものを省略すると、テーブルと ID を持つプロジェクションのこの組み合わせを持たないテーブルをクエリすることができます。現在、これらのルールのいずれにも違反するタイプがアプリケーションで定義されていない可能性がありますが、コンパイラーはそれを認識していません。適切な型情報を提供することは避けられません。

2番目の質問については、構文が冗長であると考えているという理由だけで、リフレクションを使用することはお勧めできません。型パラメーターを指定するだけで型安全性を保証できる場合は、そうすることをお勧めします。そのような方法で Scala を書くのは、非常に悪い趣味とスタイルです。Unicorn でタイプセーフ ID を採用し、後でリフレクションでそのタイプ セーフをハックするのは皮肉なことです。

さらに、 aManifestは必要なものではありません。マニフェストでは、コンパイラに提供する型情報を少なくすることはできません。マニフェストを使用すると、指定する場所をより柔軟に指定できるようになります。これにより、コンパイル時にコンパイラの型に関する知識を活用して、型消去によって生じるいくつかの問題を回避できます。ここで直面する問題は型消去とは関係がないため、Manifests は機能しません。最後に、型情報をまだ提供していない場合、Slick の内部関数ではコンパイルできないため、ランタイム リフレクションはここではあまり役に立ちません。

ええ、あなたが望むことは不可能です。Scala (および Slick) はコンパイル時に完全な情報を必要とし、それを回避するのに有効なトリックはありません。

于 2014-04-25T18:35:47.373 に答える