私は Scala にかなり慣れていないので、Scala のディープ エンドに飛び込んだような気がします。ジェネリック (ただし制限付き) 型で動作するコレクション (ArrayBuffer に似たコレクションと Array に似たコレクション) を 2 つ (エラー、拡張) 作成する必要があります。これについてどうすればよいかについての考えはありますが、私のアプローチ全体が間違っている可能性も十分にあります。
私がやろうとしていることの本質は、以下のコードから明らかです。特定の型で区切られた各コンポーネント オブジェクトを使用して、「複合オブジェクト」のコレクションを作成できるようにしたいと考えています。以下のコードでは、Meal
object は にすることはできますMeal[Beef, Broccoli]
が、することはできませんMeal[Carrots, Broccoli]
。次に、複合オブジェクト用に 2 つのコレクション クラス (Buffer のようなものと IndexedSeq のようなもの) を作成します。参考までに、私はThe Architecture of Scala Collectionsを使用しています。
package food
import collection.mutable.ArrayBuffer
import collection.{mutable, IndexedSeqLike}
import collection.generic.CanBuildFrom
// basic objects
abstract class Food {
val isCooked: Boolean
}
abstract class Protein extends Food
abstract class Vegetable extends Food
case class Beef(isCooked: Boolean) extends Protein
case class Fish(isCooked: Boolean) extends Protein
case class Carrots(isCooked: Boolean) extends Vegetable
case class Broccoli(isCooked: Boolean) extends Vegetable
// Composite Object
class Meal[Protein, Vegetable](protein: Protein, vegetable: Vegetable)
// Buffer Container
class MealsBuffer[Protein, Vegetable] extends ArrayBuffer[Meal[Protein, Vegetable]]
// Fixed-Size Container
final class MealsSeq[Protein, Vegetable] private (data: Array[Meal[Protein, Vegetable]])
extends IndexedSeq[Meal[Protein, Vegetable]]
with IndexedSeqLike[Meal[Protein, Vegetable], MealsSeq[Protein, Vegetable]] {
import MealsSeq._
// Mandatory re-implementation of `newBuilder` in `IndexedSeq`
override protected[this] def newBuilder: mutable.Builder[Meal[Protein, Vegetable], MealsSeq[Protein, Vegetable]] = MealsSeq.newBuilder
// Mandatory implementation of `apply` in `IndexedSeq`
def apply(idx: Int): Meal[Protein, Vegetable] = {
if (idx < 0 || length <= idx)
throw new IndexOutOfBoundsException
data(idx)
}
def length: Int = data.size
}
// Fixed-Size Container Companion Object
object MealsSeq {
def fromBuffer(buf: MealsBuffer[Protein, Vegetable]): MealsSeq[Protein, Vegetable] = fromIndexedSeq(buf.toArray)
def fromBuffer(buf: ArrayBuffer[Meal[Protein, Vegetable]]): MealsSeq[Protein, Vegetable] = fromIndexedSeq(buf.toArray)
def fromIndexedSeq(buf: Array[Meal[Protein, Vegetable]]): MealsSeq[Protein, Vegetable] = new MealsSeq[Protein, Vegetable](buf)
def fromSeq(buf: Seq[Meal[Protein, Vegetable]]): MealsSeq[Protein, Vegetable] = new MealsSeq[Protein, Vegetable](buf.toArray)
def apply(bases: Meal[Protein, Vegetable]*) = fromSeq(bases)
def newBuilder: mutable.Builder[Meal[Protein, Vegetable], MealsSeq[Protein, Vegetable]] = new ArrayBuffer mapResult fromSeq
implicit def canBuildFrom: CanBuildFrom[MealsSeq[Protein, Vegetable], Meal[Protein, Vegetable], MealsSeq[Protein, Vegetable]] =
new CanBuildFrom[MealsSeq[Protein, Vegetable], Meal[Protein, Vegetable], MealsSeq[Protein, Vegetable]] {
def apply(): mutable.Builder[Meal[Protein, Vegetable], MealsSeq[Protein, Vegetable]] = newBuilder
def apply(from: MealsSeq[Protein, Vegetable]): mutable.Builder[Meal[Protein, Vegetable], MealsSeq[Protein, Vegetable]] = newBuilder
}
}
このコードはコンパイルされません。私が指摘したように、コンパニオン オブジェクトで特に問題が発生します。特に、シングルトン オブジェクトでのジェネリックの実装に関してです。
私が言ったように、私は、私が最終的に達成しようとしていることに対する正しい解決策ではない、最終的に私がレイアウトしたものに対してオープンです. どういうわけか、抽象クラスの代わりに特性を使用する必要がありますか? 制限されたジェネリックとポリモーフィズムの代わりに暗黙の変換? Meals
複合オブジェクトの継承ではなく、複合でやろうとしていることを強制する方法はありますか? これはどういうわけか、より高い種類の型を使用する場所ですか? Scala には Java にはない機能がありすぎて、頭がぐるぐるしています。
アップデート
明確にするために、私がしなければならないことの範囲は次のとおりです。1 つは Array 風、もう 1 つは ArrayBuffer 風の 2 つのコレクションが必要です。コレクションは、サブエンティティのペアで構成されるエンティティを保持し、各サブエンティティには特定の制限があります。この例では、コレクションは 1 つのタンパク質と 1 つの野菜だけで構成される食事用です。コレクションは最終的に、特殊な動作とメソッドで拡張する必要があります。また、メソッドの特定の実装をオーバーライドして、特定のユースケースでより効率的にする機能も必要になります。任務はその程度です。私はそれを達成する最も簡単な方法を探しています。