Как сделать метод, возвращающий тип, универсальным?

Более простой способ - использовать force_login , новый в Django 1.9.

force_login(user, backend=None)

Например:

class LoginView(TestCase):
    def setUp(self):
        self.client.force_login(User.objects.get_or_create(username='testuser')[0])

538
задан Lii 16 May 2016 в 09:40
поделиться

10 ответов

Вы могли определить callFriend этот путь:

public <T extends Animal> T callFriend(String name, Class<T> type) {
    return type.cast(friends.get(name));
}

Тогда вызов это как таковой:

jerry.callFriend("spike", Dog.class).bark();
jerry.callFriend("quacker", Duck.class).quack();

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

823
ответ дан laz 16 May 2016 в 09:40
поделиться
  • 1
    Не делайте подделывателя для окружения [self.tableView beginUpdates] и [self.tableView endUpdates] – SwiftArchitect 3 April 2014 в 00:52

Вот более простая версия:

public <T> T callFriend(String name) {
    return (T) friends.get(name); //Casting to T not needed in this case but its a good practice to do
}

Полностью рабочий код:

    public class Test {
        public static class Animal {
            private Map<String,Animal> friends = new HashMap<>();

            public void addFriend(String name, Animal animal){
                friends.put(name,animal);
            }

            public <T> T callFriend(String name){
                return (T) friends.get(name);
            }
        }

        public static class Dog extends Animal {

            public void bark() {
                System.out.println("i am dog");
            }
        }

        public static class Duck extends Animal {

            public void quack() {
                System.out.println("i am duck");
            }
        }

        public static void main(String [] args) {
            Animal animals = new Animal();
            animals.addFriend("dog", new Dog());
            animals.addFriend("duck", new Duck());

            Dog dog = animals.callFriend("dog");
            dog.bark();

            Duck duck = animals.callFriend("duck");
            duck.quack();

        }
    }
12
ответ дан mppfiles 16 May 2016 в 09:40
поделиться

Едва ли, потому что, как Вы говорите, компилятор только знает, что callFriend () возвращает Животное, не Собаку или Утку.

разве Вы не можете добавить краткий обзор makeNoise () метод Животному, которое было бы реализовано как кора или шарлатан ее подклассами?

2
ответ дан sk. 16 May 2016 в 09:40
поделиться
  • 1
    Я стремлюсь избежать сторонних дополнений, если дополнение должно быть установлено на каждой машине с помощью решения. В случае Xsd2Code было бы выполнимо иметь дополнение на одной машине только? – MrEyes 3 February 2011 в 12:37

Поскольку Вы сказали, что передача класса будет в порядке, Вы могли записать это:

public <T extends Animal> T callFriend(String name, Class<T> clazz) {
   return (T) friends.get(name);
}

И затем используют его как это:

jerry.callFriend("spike", Dog.class).bark();
jerry.callFriend("quacker", Duck.class).quack();

Не прекрасный, но это в значительной степени, насколько Вы добираетесь с дженериками Java. Существует способ реализовать Безопасные с точки зрения типов неоднородные контейнеры (THC) с помощью Супер Маркеров Типа , но это имеет его собственные проблемы снова.

9
ответ дан Fabian Steeg 16 May 2016 в 09:40
поделиться
  • 1
    Потрясающий. Никогда не знал то, для чего была та внешняя опция инструментов. СТОЛЬКО НОВЫХ ОПЕРАЦИЙ – Ryan Bennett 7 November 2013 в 16:32

Нет. Компилятор не может знать то, что возвратил бы тип jerry.callFriend("spike"). Кроме того, Ваша реализация просто скрывает бросок в методе без любой дополнительной безопасности типов. Рассмотрите это:

jerry.addFriend("quaker", new Duck());
jerry.callFriend("quaker", /* unused */ new Dog()); // dies with illegal cast

В этом конкретном случае, создавая метод краткого обзора talk() и переопределяя его соответственно в подклассах служил бы Вам намного лучше:

Mouse jerry = new Mouse();
jerry.addFriend("spike", new Dog());
jerry.addFriend("quacker", new Duck());

jerry.callFriend("spike").talk();
jerry.callFriend("quacker").talk();
113
ответ дан Andrei Volgin 16 May 2016 в 09:40
поделиться

На основе той же идеи как Супер Маркеры Типа Вы могли создать введенный идентификатор для использования вместо строки:

public abstract class TypedID<T extends Animal> {
  public final Type type;
  public final String id;

  protected TypedID(String id) {
    this.id = id;
    Type superclass = getClass().getGenericSuperclass();
    if (superclass instanceof Class) {
      throw new RuntimeException("Missing type parameter.");
    }
    this.type = ((ParameterizedType) superclass).getActualTypeArguments()[0];
  }
}

, Но я думаю, что это может победить цель, так как теперь необходимо создать новые идентификационные объекты для каждой строки и держаться за них (или восстановить их с корректной информацией о типе).

Mouse jerry = new Mouse();
TypedID<Dog> spike = new TypedID<Dog>("spike") {};
TypedID<Duck> quacker = new TypedID<Duck>("quacker") {};

jerry.addFriend(spike, new Dog());
jerry.addFriend(quacker, new Duck());

, Но можно теперь использовать класс в способе, которым Вы первоначально хотели без бросков.

jerry.callFriend(spike).bark();
jerry.callFriend(quacker).quack();

Это просто скрывает параметр типа в идентификаторе, хотя это действительно означает, что можно получить тип от идентификатора позже, если Вы желаете.

необходимо было бы реализовать сравнение и методы хеширования TypedID также, если Вы хотите быть в состоянии сравнить два идентичных экземпляра идентификатора.

8
ответ дан Mike Houston 16 May 2016 в 09:40
поделиться
  • 1
    Спасибо, но установить пространство имен сгенерированного класса я должен был сделать маленькую модификацию. Добавьте/n:" Пространство имен Here" к Аргументам и нажимают на " Подсказка для aguments". теперь просто необходимо изменить Пространство имен Здесь на пространство имен, когда тогда подсказка подходит. Я первоначально пытался использовать пространство имен по умолчанию, но couldn' t видят способ сделать это. Если кто-либо знает лучший путь, тогда сообщенный мне. Спасибо – nfplee 12 September 2013 в 10:37

Этот вопрос очень похож на , Объект 29 в Эффективном Java - "Рассматривает безопасные с точки зрения типов неоднородные контейнеры". Ответ Laz является самым близким к решению Bloch. Однако оба помещенные и добираются, должен использовать литерал Класса для безопасности. Подписи стали бы:

public <T extends Animal> void addFriend(String name, Class<T> type, T animal);
public <T extends Animal> T callFriend(String name, Class<T> type);

Внутренняя часть оба метода необходимо проверить, что параметры нормальны. Посмотрите Эффективный Java и Класс javadoc для большего количества информации

27
ответ дан Craig P. Motlin 16 May 2016 в 09:40
поделиться

Вы могли реализовать его как это:

@SuppressWarnings("unchecked")
public <T extends Animal> T callFriend(String name) {
    return (T)friends.get(name);
}

(Да, это - свод законов; см. Дженерики Java: Универсальный тип определяется как тип возврата [только 116].)

тип возврата будет выведен от вызывающей стороны. Однако отметьте @SuppressWarnings аннотация: это говорит Вам, что этот код не безопасен с точки зрения типов . Необходимо проверить его сами, или Вы могли добраться ClassCastExceptions во времени выполнения.

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

jerry.<Dog>callFriend("spike").bark();

, В то время как это может быть немного более хорошо, чем кастинг, Вы - вероятно, более обеспеченное предоставление Animal, классифицируют метод краткого обзора talk(), как сказал David Schmitt.

101
ответ дан Community 16 May 2016 в 09:40
поделиться
  • 1
    Выбранный как ответ из-за простоты, Brian' s ответ также совершенно хорошо, но этого легче понять и поддержать. – Malfist 12 January 2011 в 21:24

Не возможный. Как Карта, как предполагается, знает, какой подкласс Животного она собирается получить, учитывая только Строковый ключ?

единственный способ, которым это было бы возможно, состоит в том, если бы каждое Животное приняло только один тип друга (тогда, то это мог бы быть параметр класса Животных), или callFriend (), метод получил параметр типа. Но действительно похоже, что Вы упускаете суть наследования: это - это, можно только рассматривать подклассы однородно при использовании исключительно методов суперкласса.

5
ответ дан Michael Borgwardt 16 May 2016 в 09:40
поделиться
  • 1
    Слишком плохо; there' s никакой MaximumSize свойство для ToolStripButton. – Danny Beckett 4 July 2013 в 16:14

Я написал статью, которая содержит подтверждение концепции, классы поддержки и тестовый класс, который демонстрирует, как Супер Маркеры Типа могут быть получены Вашими классами во времени выполнения. Короче говоря это позволяет Вам делегировать к альтернативным реализациям в зависимости от фактических универсальных параметров, переданных вызывающей стороной. Пример:

  • TimeSeries<Double> делегаты в частном внутреннем классе, который использует double[]
  • TimeSeries<OHLC> делегаты в частном внутреннем классе, который использует ArrayList<OHLC>

См.: Используя TypeTokens для получения универсальных параметров

Спасибо

Richard Gomes - Блог

5
ответ дан 22 November 2019 в 22:16
поделиться
Другие вопросы по тегам:

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