3

私はJavaコードで次の定義を持っています:

抽象ポート定義 (具象ポート クラスによって型指定):

package test;

public class Port<
     PortOptions extends Port.Options, 
     ConcretePort extends Port<PortOptions, ConcretePort>> {

    public interface Options {
    }

}

ポート サービスの定義 (何らかのコールバック メカニズムを介してポートで何らかの処理を行うことができます)

package test;

import java.util.Set;

public class PortService {
    public interface Callback<T> {
        void processData(T data);
    }

    public void methodWithCallback(Callback<Set<Port>> callback) {

    }
}

そして、scala からポート サービスにコールバックを登録したいと考えています。私が試したのはこれです:

package test

import test.PortService.Callback
import java.util

class PortServiceCaller {

    def callingMethod() {
        val portService: PortService = new PortService

        portService.methodWithCallback(new Callback[java.util.Set[Port[_, _]]] {
            def processData(data: util.Set[Port[_, _]]) {

            }
        })
    }
}

そして、それは惨めに失敗します:

error: type mismatch;
found   : java.lang.Object with test.PortService.Callback[java.util.Set[test.Port[_, _]]]
required: test.PortService.Callback[java.util.Set[test.Port[_ <: test.Port.Options, _ <: test.Port[?0,?1]]]]
portService.methodWithCallback(new Callback[java.util.Set[Port[_, _]]] {

問題は、Java サービスを適切に呼び出せるようにするための scala コードの書き方です。

私はscala型付けシステムを見てきましたが、それを理解できないようです.

後で編集:

解決策は実際には非常に簡単です。

コールバック メソッドを次のように宣言します。

    public void methodWithCallback(Callback<Set<Port<?, ?>>> callback) {

    }

次のようにscalaから呼び出します。

    portService.methodWithCallback(new Callback[java.util.Set[Port[_, _]]] {
        def processData(data: java.util.Set[Port[_, _]]) {
        }
    })

また、両方の言語の型システムを考えると理にかなっています。

4

1 に答える 1

3

Java で行っていることは何か危険であり、コードがコンパイルされるのは、Java コンパイラが遅延していてチェックしないからです。あなたが書くとき:

   public void methodWithCallback(Callback<Set<Port>> callback) {

    }

基本的に、Port に関するすべての型情報を破棄しています。

Port<PortOptions extends Port.Options, ConcretePort extends Port<PortOptions, ConcretePort>>

すべての情報を利用できるわけではなく、Java コンパイラーでは型パラメーターを省略できます。scala ではこれは不可能であり、型パラメーターを表現するだけでなく、型制約も正しく表現する必要があります。ここでの最初の質問は、未知の型があることさえ言わずに、なぜ Port を書いているのかということです。

public void methodWithCallback(Callback<Set<Port<?,?>>> callback) {

}

が正しい書き方になります。

複数の未知の型の間の境界関係を表現したい場合、単純な境界に適した存在型にコンパクト _ を使用することはできませんが、 forSome を使用する必要があります

  class Port[A,B<:A]

  def myMethod(a:Port[A,B]forSome {type B; type B<:A})

しかし、私がよく言うように、これらのパターンを使用してしまうと、デザインが弱くなり、問題を解決するためのよりクリーンでエレガントな方法が得られる可能性があります。型安全性に関する情報を破棄する必要がある場合、ジェネリックを使用する意味は何ですか?

于 2012-07-24T13:51:23.963 に答える