Объединение в цепочку метода + наследование не играет хорошо вместе?

Я испытал затруднения, заставив мерзавца сотрудничать с wordpad, KomodoEdit и в значительной степени любым редактором, которого я даю ему. Самый открытый для редактирования, но мерзавца ясно не ожидает сохранения/близко к, происходят.

Как опора, я просто делал т.е.

git commit -m "Fixed the LoadAll method"

, чтобы поддерживать движение вещей. Имеет тенденцию сохранять мои сообщения о фиксации немного короче, чем они, вероятно, должны быть, но ясно существует некоторая работа, которая будет сделана на версии Windows мерзавца.

GitGUI также не это плохо. Требуется определенная ориентация, но после этого, это работает довольно хорошо.

38
задан Community 23 May 2017 в 12:09
поделиться

5 ответов

Если вы хотите избежать непроверенных предупреждений приведения от вашего компилятора (и не хотите @SuppressWarnings ("unchecked")), то вам нужно сделать еще немного:

Прежде всего, ваше определение Pet должно быть самореферентным, потому что Pet всегда является универсальным типом:

abstract class Pet <T extends Pet<T>>

Во-вторых, (T) это приведение в setName также не отмечено. Чтобы избежать этого, используйте технику "getThis" из превосходного FAQ по Generics от Анжелики Лангер :

Уловка "getThis" предоставляет способ восстановить точный тип этого ссылка.

В результате получается приведенный ниже код, который компилируется и запускается без предупреждений. Если вы хотите расширить свои подклассы, этот метод все еще остается в силе (хотя вам, вероятно, потребуется обобщить ваши промежуточные классы).

В результате получается следующий код:

public class TestClass {

  static abstract class Pet <T extends Pet<T>> {
    private String name;

    protected abstract T getThis();

    public T setName(String name) {
      this.name = name;
      return getThis(); }  
  }

  static class Cat extends Pet<Cat> {
    @Override protected Cat getThis() { return this; }

    public Cat catchMice() {
      System.out.println("I caught a mouse!");
      return getThis();
    }
  }

  static class Dog extends Pet<Dog> {
    @Override protected Dog getThis() { return this; }

    public Dog catchFrisbee() {
      System.out.println("I caught a frisbee!");
      return getThis();
    }
  }

  public static void main(String[] args) {
    Cat c = new Cat();
    c.setName("Morris").catchMice();
    Dog d = new Dog();
    d.setName("Snoopy").catchFrisbee();
  }
}
55
ответ дан 27 November 2019 в 03:17
поделиться

Как насчет этого старого трюка:

abstract class Pet<T extends Pet>
{
    private String name;
    public T setName(String name) { this.name = name; return (T) this; }        
}

class Cat extends Pet<Cat>
{
    /* ... */
}

class Dog extends Pet<Dog>
{
    /* ... */
}
20
ответ дан 27 November 2019 в 03:17
поделиться

Нет, не совсем. Вы можете обойти это, используя ковариантные возвращаемые типы (спасибо Макдауэллу за правильное имя):

@Override
public Cat setName(String name) {
    super.setName(name);
    return this;
}

(Ковариантные возвращаемые типы есть только в Java 5 и выше, если вас это беспокоит.)

10
ответ дан 27 November 2019 в 03:17
поделиться
public class Pet<AnimalType extends Pet> {

private String name;
    public AnimalType setName(String name) {
       this.name = name; return (AnimalType)this; 
    }        
}

и

public class Cat extends Pet<Cat> {

    public Cat catchMice() {return this;}

    public static void main(String[] args) {
        Cat c = new Cat().setName("bob").catchMice();
    }

}

3
ответ дан 27 November 2019 в 03:17
поделиться

Это немного запутано, но вы можете сделать это с помощью дженериков:

abstract class Pet< T extends Pet > {
    private String name;

    public T setName( String name ) {
        this.name = name;
        return (T)this;
    }

    public static class Cat extends Pet< Cat > {
        public Cat catchMice() {
            System.out.println( "I caught a mouse!" );
            return this;
        }
    }

    public static class Dog extends Pet< Dog > {
        public Dog catchFrisbee() {
            System.out.println( "I caught a frisbee!" );
            return this;
        }
    }

    public static void main (String[] args){
        Cat c = new Cat();
        c.setName( "Morris" ).catchMice(); // error! setName returns Pet, not Cat
        Dog d = new Dog();
        d.setName( "Snoopy" ).catchFrisbee(); // error! setName returns Pet, not Dog
    }

}
5
ответ дан 27 November 2019 в 03:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: