7

実装されたクラスのタイプに対して、それを実装する各クラスに特定の機能を強制するインターフェイスを作成したいと考えています。

したがって、MyClassA、MyClassB、MyClassC などのクラスがあり、すべて独自の型の関数が必要だとします。

MyClassA で:

public class MyClassA implements MyClass {
    MyClassA function(MyClassA x) {
        doSomethingImplementedInMyClassA(x);
    }
}

MyClassB:

public class MyClassB implements MyClass {
    MyClassB function(MyClassB x) {
        doSomethingImplementedInMyClassB(x);
    }
}

MyClass問題は、そのような機能を必要とするインターフェイスをどのように作成するかです。

public interface MyClass {
    MyClass function(MyClass x);
}

返される型は MyClass であり、その実装ではないため、明らかに機能しません。Javaでこれを適切に行うには?

4

4 に答える 4

11

ジェネリックを使用できます:

public interface MyClass<V extends MyClass<V>> {
    V function(V x);
}

public class MyClassA implements MyClass<MyClassA> 

これはCRTPと呼ばれます。


これは完璧ではありません。それはまだ次のようなことを許可します

public class MyClassB implements MyClass<MyClassA> 

これを正しく行うには、Java がサポートしていない高次の型[要出典]が必要です。

于 2012-09-02T02:16:39.847 に答える
1

実装が常に引数のメソッドを呼び出す場合は、そのメソッドをインターフェイスに追加しないのはなぜですか?

interface MyClass {
    MyClass doSomething();
}

class MyClassA implements MyClass {
    MyClassA doSomething() {
        //implementation here
    }
}

class MyClassB implements MyClass {
    MyClassB doSomething() {
        //implementation here
    }
}
于 2012-09-02T02:40:07.420 に答える
1

おそらく必要なのは、インターフェイスとは別の親クラスです。

インターフェイスは動作を定義するために理想的に使用されるため、のように動作するのでGroupElementA GroupElementなく、概念的により正確に聞こえます。GroupElementA GroupElement

親クラスを使用して、必要なものを実現することを検討します。

/**
 * An abstract group element.
 */
abstract class GroupElement
{
    // attributes of all group elements
}

/**
 * Defines behavior for objects that can be multiplied with
 * GroupElements.
 */
interface GroupElementMultipliable
{
    public GroupElement multiplyBy(GroupElement groupElement);
}

/**
 * Defines behavior for objects that can be divided by
 * GroupElements.
 */
interface GroupElementDivisible
{
    public GroupElement divideBy(GroupElement groupElement);
}

/**
 * An abstract GroupElement that can perform operations like
 * multiplication and division.
 *
 * Then again this class may not be necessary. The interfaces
 * implemented here may actually be directly implemented by
 * GroupElementA. GroupElementA will also be the one to inherit
 * GroupElement.
 */
abstract class OperableGroupElement extends GroupElement
        implements GroupElementMultipliable, GroupElementDivisible
{
    // attributes of all operable group elements
}

/**
 * A concrete GroupElement that can perform operations like
 * multiplication and division.
 */
class GroupElementA extends OperableGroupElement
{
    @Override
    public GroupElementA multiplyBy(GroupElement groupElement)
    {
        // Since we expect to multiply with another GroupElementA
        // we attempt to typcast the groupElement
        GroupElementA groupElementA = (GroupElementA) groupElement;

        // do multiplication operation -- this * groupElementA
        // then return new self
        return this;
    }

    @Override
    public GroupElementA divideBy(GroupElement groupElement)
    {
        // Since we expect to divide by another GroupElementA
        // we attempt to typcast the groupElement
        GroupElementA groupElementA = (GroupElementA) groupElement;

        // do division operation -- this / groupElementA
        // then return new self
        return this;
    }
}
于 2012-09-02T04:01:21.103 に答える
1

Java でやりたいことを行う適切な方法は次のとおりです。

まず、抽象メソッドを含むインターフェイスを定義します。これは、まだ定義されていないメソッドです。インターフェイスはクラスではないことに注意してください。

public interface Animal {
    public Animal reproduceWith(Animal someAnimal);
}

次に、インターフェイスを実装するクラスを定義し、抽象メソッドをオーバーライドしますが、選択したコードで実装します。そうすれば、クラス内で同じものはメソッド名だけです。これにより、クラスに特定のメソッドを実装することが効果的に強制されます。

public class Dog implements Animal {

    @Override
    public Animal reproduceWith(Animal someAnimal) {
        return new Dog();
    }
}


public class Cat implements Animal {

    @Override
    public Animal reproduceWith(Animal someAnimal) {
        return new Cat();
    }
}

その後、たとえばMyInterfaceのリストを作成し、それが別のクラスであっても同じメソッドを呼び出して反復することができます。

List<Animal> list = new ArrayList<Animal>();
list.add(new Cat());
list.add(new Dog());

Animal cat = new Cat();
Animal dog = new Dog();

for (Animal animal : list) {
    System.out.println(animal.reproduceWith(cat));
    System.out.println(animal.reproduceWith(dog));
}

それがあなたを助けることを願っています。

于 2012-09-02T02:45:50.313 に答える