Что отличает mixin от множественного наследования? Это только вопрос семантики?
blockquote>Смесин - это ограниченная форма множественного наследования. В некоторых языках механизм добавления mixin к классу несколько отличается (в терминах синтаксиса) от наследования.
В контексте Python, особенно, mixin является родительским классом, который предоставляет функциональные возможности для подклассы, но не предназначены для создания самого себя.
Что может заставить вас сказать: «Это просто множественное наследование, а не просто mixin», если класс, который может быть запутан для mixin, может быть фактически создан и использован - так что это действительно семантика, и очень реальная разница.
Пример множественного наследования
Этот пример, из документации , является OrderedCounter:
blockquote>class OrderedCounter(Counter, OrderedDict): 'Counter that remembers the order elements are first encountered' def __repr__(self): return '%s(%r)' % (self.__class__.__name__, OrderedDict(self)) def __reduce__(self): return self.__class__, (OrderedDict(self),)
Он подклассифицирует как
Counter
, так иOrderedDict
из модуляcollections
.Оба
Counter
иOrderedDict
предназначены для создания и использования самостоятельно. Однако, подклассифицируя их оба, мы можем иметь счетчик, который упорядочен и повторно использует код в каждом объекте.Это мощный способ повторного использования кода, но также может быть проблематичным. Если окажется, что в одном из объектов есть ошибка, исправление без забот может создать ошибку в подклассе.
Пример Mixin
Микшины обычно рекламируются как способ повторного использования кода без потенциальных проблем связи, которые могут иметь совместное множественное наследование, например OrderedCounter. Когда вы используете mixins, вы используете функциональные возможности, которые не так тесно связаны с данными.
В отличие от вышеприведенного примера, mixin не предназначен для использования сам по себе. Он предоставляет новую или различную функциональность.
Например, стандартная библиотека имеет пару миксинов в библиотеке
socketserver
.Forking и потоковые версии каждого типа сервера могут быть созданы с использованием этих классов смешения. Например, ThreadingUDPServer создается следующим образом:
class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass
Класс mix-in приходит первым, поскольку он переопределяет метод, определенный в UDPServer. Установка различных атрибутов также изменяет поведение базового механизма сервера.
blockquote>В этом случае методы mixin переопределяют методы в определении объекта
UDPServer
, чтобы разрешить параллелизм.Переопределенный метод представляется
process_request
, а также предоставляет другой методprocess_request_thread
. Здесь это из исходного кода :blockquote>class ThreadingMixIn: """Mix-in class to handle each request in a new thread.""" # Decides how threads will act upon termination of the # main process daemon_threads = False def process_request_thread(self, request, client_address): """Same as in BaseServer but as a thread. In addition, exception handling is done here. """ try: self.finish_request(request, client_address) except Exception: self.handle_error(request, client_address) finally: self.shutdown_request(request) def process_request(self, request, client_address): """Start a new thread to process the request.""" t = threading.Thread(target = self.process_request_thread, args = (request, client_address)) t.daemon = self.daemon_threads t.start()
Проприведенный пример
Это миксин, который в основном используется для демонстрационные цели - большинство объектов будут развиваться за пределами полезности этого представления:
class SimpleInitReprMixin(object): """mixin, don't instantiate - useful for classes instantiable by keyword arguments to their __init__ method. """ __slots__ = () # allow subclasses to use __slots__ to prevent __dict__ def __repr__(self): kwarg_strings = [] d = getattr(self, '__dict__', None) if d is not None: for k, v in d.items(): kwarg_strings.append('{k}={v}'.format(k=k, v=repr(v))) slots = getattr(self, '__slots__', None) if slots is not None: for k in slots: v = getattr(self, k, None) kwarg_strings.append('{k}={v}'.format(k=k, v=repr(v))) return '{name}({kwargs})'.format( name=type(self).__name__, kwargs=', '.join(kwarg_strings) )
и использование будет:
class Foo(SimpleInitReprMixin): # add other mixins and/or extend another class here __slots__ = 'foo', def __init__(self, foo=None): self.foo = foo super(Foo, self).__init__()
И использование:
>>> f1 = Foo('bar') >>> f2 = Foo() >>> f1 Foo(foo='bar') >>> f2 Foo(foo=None)
Источники находятся в src.zip
, расположенном в папке установки:
JDK включает src.zip
по умолчанию , если я хорошо помню.
В дистрибутиве Linux может потребоваться установить пакет sun-java6-source
.
На компьютере Mac необходимо загрузить документацию для разработчиков. Посмотрите на этот ответ .
Это правильное поведение
JSON может содержать только данные, а не методы - он должен быть независимым от языка, поэтому кодирование объектных методов не имеет смысла.
Это сделает трюк..
SELECT *
FROM my_table
WHERE 1
ORDER BY
CASE price WHEN 0 THEN 1
ELSE -1
END ASC, price asc, id asc
Вы также можете использовать следующее:
SELECT *
FROM my_table
WHERE 1
ORDER BY price=0, price, id;
Часть 'price = 0' будет равна 1 для товаров с нулевой ценой и 0 для товаров с ненулевой ценой. Поскольку порядок сортировки по умолчанию - ASC, ненулевые элементы теперь размещаются первыми.
Следующий бит предложения order-by означает, что ненулевые товары затем сортируются по цене (снова по возрастанию). Если какие-либо предметы с ненулевой ценой имеют одинаковую цену, они будут отсортированы по идентификатору, но нас это не волнует.
Последняя часть предназначена только для товаров, у которых цена = 0. Поскольку все эти предметы имеют одинаковую цену, результатом будет сортировка всех предметов с нулевой ценой по идентификатору.