Apakah Scala memiliki sesuatu yang mirip dengan implementasi antarmuka eksplisit C#?

Di C#, Anda dapat mengimplementasikan antarmuka secara eksplisit. Metode yang diimplementasikan secara eksplisit hanya dapat dipanggil melalui variabel yang memiliki antarmuka sebagai tipe statisnya. Hal ini memungkinkan Anda menghindari konflik nama/tipe pengembalian dan menyediakan implementasi berbeda dari metode yang sama bergantung pada tipe statis this.

Misalnya:

interface IFoo
{
    int DoSomething();
}

interface IBar
{
    string DoSomething();
}

class Impl : IFoo, IBar
{
    int IFoo.DoSomething() { /* Implementation for IFoo */ }
    string IBar.DoSomething() { /* A different implementation for IBar */ }
    public void DoSomething() { /* Yet another implementation for Impl */ }
}

Bagaimana Anda menangani kasus ini di Scala:

trait Foo {
    def doSomething(): Int
}

trait Bar {
    def doSomething(): String
}

class Impl extends Foo with Bar {
    /* only one "doSomething()" visible here (that of Bar?) */
    /* what now... ? */
}

person Tobias Brandt    schedule 16.07.2013    source sumber
comment
Anda dapat menggunakan obat generik T? Tidak 100% apa yang Anda maksudkan tetapi sepertinya Anda bisa menggunakannya. Anda mencoba mengembalikan tipe berbeda berdasarkan metode tanda tangan yang sama? Misalnya: Anda dapat memiliki T DoSomething‹T›();   -  person Dr Schizo    schedule 16.07.2013


Jawaban (2)


Jika Anda hanya mencoba membuat kelas Anda mengikuti dua antarmuka terpisah yang tidak kompatibel, Anda harus menulis wrapper. Contohnya,

implicit case class ImplAsFoo(impl: Impl) extends Foo {
  def asFoo = this
  def doSomething: Int = 5
}

Sekarang kamu bisa

impl.asFoo

di situs penggunaan untuk beralih ke pembungkus Foo.

Namun, dalam beberapa kasus, mungkin lebih alami menggunakan pola kelas tipe untuk menyediakan fungsionalitas yang dapat dicolokkan:

trait IFoo[A] { def doSomething: Int }
trait IBar[A] { def doSomething: String }

// These need to be companions so :paste if you're using REPL
class Impl { def doSomething { println("Hey!") } }
object Impl {
  implicit object FooImpl extends IFoo[Impl] { def doSomething = 5 }
  implicit object BarImpl extends IBar[Impl] { def doSomething = "salmon" }
}

def needsFoo[A <: Impl: IFoo](a: A) = implicitly[IFoo[Impl]].doSomething

scala> needsFoo(new Impl)
res1: Int = 5

scala> (new Impl).doSomething
Hey!

Ini tidak persis sama, tetapi ini juga menangani masalah penerapan yang berbeda tanpa memberi nama skema yang membuat Anda tersandung. (Jika Anda perlu doSomething dengan objek impl, Anda akan meneruskannya sebagai parameter di implicit object yang menangani kasus tersebut.)

Jika Anda sudah memiliki ciri-cirinya, tentu saja hal ini tidak akan membantu Anda. Namun ketika Anda mendesain dari awal, daripada memiliki tumpukan sifat dengan metode yang tidak kompatibel, Anda mungkin mencoba kelas tipe.

Terakhir, jika Anda tidak dapat menahan diri untuk mencampurkan banyak hal yang belum diketik sehingga Anda harus memilih Foo, Anda harus membuat skema yang lebih rumit seperti ini:

trait CanBeFoo { def asFoo: Foo }
trait Foo { def doSomething: Int }

// :paste these two together
class Impl extends CanBeFoo {
  def doSomething { println("Ho!") } 
  def asFoo = ImplAsFoo(this)
}
case class ImplAsFoo(impl: Impl) extends Foo {
  def doSomething = 6
}

val myList = List("salmon", new Impl, new Foo { def doSomething = 4 })
def doIt(f: Foo) { println(f.doSomething) }
myList.foreach {
  case f: Foo => doIt(f)
  case cf: CanBeFoo => doIt(cf.asFoo)
  case _ => println("nuh-uh")
}

// Produces
// nuh-uh
// 6
// 4

Anda mungkin lebih memilih peta perantara:

myList.map{ case cf: CanBeFoo => cf.asFoo; case x => x }.foreach{
  case f: Foo => println(f.doSomething)
  case _ => println("nuh-uh")
}
person Rex Kerr    schedule 16.07.2013

Tidak, itu adalah tipe dasar yang sangat tidak kompatibel. Ketika suatu kelas memperluas suatu sifat, ia mempunyai sifat itu sebagai bagian dari identitas tipenya. Itu tidak boleh memiliki identitas tipe yang saling tidak kompatibel seperti yang terjadi pada kelas mana pun yang extends Foo with Bar (saat Anda menulis sifat-sifat tersebut).

person Randall Schulz    schedule 16.07.2013