Зачем использовать расширение и реализовать в то же время [дубликат]

Такое поведение неудивительно, если принять во внимание следующее:

  1. Поведение атрибутов класса только для чтения при попытках назначения и что
  2. Функции являются объектами (хорошо объясняется в принятом ответе).

Роль (2) была широко освещена в этой теме. (1), вероятно, является фактором, вызывающим удивление, поскольку это поведение не является «интуитивным» при поступлении с других языков.

(1) описано в учебнике Python по классам . При попытке присвоить значение атрибуту класса только для чтения:

... все переменные, найденные вне самой внутренней области, доступны только для чтения ( попытка написать такую переменная просто создаст новую локальную переменную в самой внутренней области, оставив неизмененную идентичную внешнюю переменную неизменной ).

blockquote>

Оглянитесь на исходный пример и рассмотрите приведенные выше пункты:

def foo(a=[]):
    a.append(5)
    return a

Здесь foo - объект, а a - атрибут foo (доступен в foo.func_defs[0]). Поскольку a является списком, a является изменяемым и, таким образом, является атрибутом чтения-записи foo. Он инициализируется пустым списком, указанным сигнатурой при создании экземпляра функции, и доступен для чтения и записи до тех пор, пока существует функциональный объект.

Вызов foo без переопределения значения по умолчанию использует значение по умолчанию от foo.func_defs. В этом случае foo.func_defs[0] используется для a в пределах области кода объекта объекта. Изменения в a меняют foo.func_defs[0], который является частью объекта foo и сохраняется между выполнением кода в foo.

Теперь сравните это с примером из документации по , эмулируя поведение аргументов по умолчанию других языков , так что значения по умолчанию для функции используются каждый раз, когда функция выполняется:

def foo(a, L=None):
    if L is None:
        L = []
    L.append(a)
    return L

Принимая во внимание (1) и (2) , можно понять, почему это выполняет желаемое поведение:

  • Когда объект функции foo создается, foo.func_defs[0] установлен на None, неизменяемый объект.
  • Когда функция выполняется с настройками по умолчанию (без функции, заданной для L в вызове функции), foo.func_defs[0] (None) доступен в локальной области как L.
  • После L = [] присваивание не может преуспеть в foo.func_defs[0], поскольку этот атрибут доступен только для чтения.
  • Per (1), новая локальная переменная с именем L создается в локальной области и используется для остальной части вызова функции. foo.func_defs[0], таким образом, остается неизменным для будущих вызовов foo.

26
задан LTH 16 December 2011 в 18:58
поделиться

7 ответов

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

Пример такого класса приведен в учебнике Oracle Object Ordering . Обратите внимание на аналогичную модель T extends Comparable<T> в выдержке ниже:

public class Name implements Comparable<Name> {
   ...
   public int compareTo(Name n) { ... }
}
29
ответ дан Andy Thomas 21 August 2018 в 04:00
поделиться
  • 1
    Почему не только имя реализует Comparable? Зачем нужно снова указывать имя класса? – committedandroider 17 February 2015 в 02:57
  • 2
    @committedandroider, потому что Comparable - это общий интерфейс, который вам нужно указать тип – bitek 23 June 2015 в 07:59
  • 3
    Это хороший ответ. Но это интересно в ограниченных типичных типах, Java не делает различий между реализацией интерфейса и наследованием класса - <T implements Comparable<T>> не является законным. – flow2k 28 June 2018 в 16:27

Java. Значение <T extends Comparable<T>>?

a) Comparable <T> - общий интерфейс (помните, что это «интерфейс», то есть не «класс»)

b ) extends означает наследование от класса или интерфейса.

С вышеуказанной точки # a это интерфейс .. (Помните, что это наследование от «интерфейса», то есть не от «класса»)

c) От выше упомянутых обеих точек #a & amp; #b,

здесь «один интерфейс» расширяет «другой интерфейс».

Для этого класса должен быть определенный интерфейс. Например, здесь есть

interface MinMax<T extends Comparable<T>> { 
    T min(); 
    T max(); 
} 

d) теперь ваш класс, т. е. public class RClass {} СЛЕДУЕТ

1 # ЭТО «реализовать» этот «общий интерфейс» Comparable<T> .. !!!

ex: public class RClass<T> implements Comparable<T>

2 # ИЛИ создать интерфейс и перейти к этому «универсальному интерфейсу» Comparable<T> ex:

interface MinMax<T extends Comparable<T>> { 
   T min(); 
   T max(); 
} 
class RClass<T extends Comparable<T>> implements MinMax<T> {
    .....
    .....
}

Здесь обратите особое внимание на то, как параметр типа T объявляется RClass, а затем передается в MinMax. Поскольку для MinMax требуется тип, реализующий Comparable, класс реализации (RClass в этом случае) должен указывать ту же самую границу. Кроме того, после того, как эта оценка была установлена, нет необходимости указывать ее снова в предложении tools.

7
ответ дан Alex Weitz 21 August 2018 в 04:00
поделиться
  • 1
    В этом вопросе было задано public **class** RClass<T extends Comparable<T>>. Это класс, а не интерфейс. Поэтому, пожалуйста, прокомментируйте, что будет означать, если это класс. – Sathish Kumar k k 9 September 2015 в 13:22

Проще говоря, общий тип T должен быть сопоставим для сравнения. иначе вы не сможете сделать T.compareTo. В пункте 28 «Эффективная Java» предлагается: "always use Comparable<? super T> in preference to Comparable<T>. <T extends Comparable<? super T>>"

1
ответ дан Andrew Xie 21 August 2018 в 04:00
поделиться

Это означает, что вы можете создать экземпляр RClass с типом, который буквально расширяет Comparable<T>. Таким образом,

RClass<Integer> a;

приемлемо, так как Integer расширяет Comparable<Integer>, а

RClass<Object> b;

не является, так как Object не является классом, который расширяется, сравнимый по все.

2
ответ дан djhaskin987 21 August 2018 в 04:00
поделиться

Да, и имейте в виду, что объекты классов, полученные из объектов Comparable ARE Comparable. Наследование - это отношение is-a.

2
ответ дан feeling unwelcome 21 August 2018 в 04:00
поделиться

Где-то в этом классе программисту нужно написать что-то вроде

if(t.compareTo(othert) < 0) {
    ...
}

. Для этого для типа T должен быть метод compareTo, который сравнивает его с другим объектом типа T. Расширение Сопоставимое гарантирует существование такого метода, среди прочего.

4
ответ дан jforberg 21 August 2018 в 04:00
поделиться

==> guhanvj, <T extends Comparable<T>> означает, что <T> имеет верхнюю границу объектов Comparable<T>. Таким образом, <T> может иметь типы классов Byte, Character, Double, Float, Long, Short, String и Integer, которые все реализуют интерфейс Comparable<T> для естественного упорядочения.

1
ответ дан PerfectionIsNotOptional. 21 August 2018 в 04:00
поделиться
Другие вопросы по тегам:

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