Что такое миксин и почему они полезны? - PullRequest
829 голосов
/ 10 февраля 2009

В « Programming Python » Марк Лутц упоминает «миксин». Я из C / C ++ / C # фона, и я не слышал этот термин раньше. Что такое миксин?

Чтение между строк этого примера (с которым я связался, потому что оно довольно длинное), я предполагаю, что это случай использования множественного наследования для расширения класса в отличие от «правильного» подклассы. Это правильно?

Зачем мне это делать, а не помещать новую функциональность в подкласс? В этом отношении, почему подход смешанного / множественного наследования лучше, чем использование композиции?

Что отличает миксин от множественного наследования? Это просто вопрос семантики?

Ответы [ 15 ]

6 голосов
/ 10 февраля 2009

Может быть, поможет пример из ruby:

Вы можете включить миксин Comparable и определить одну функцию "<=>(other)", миксин предоставляет все эти функции:

<(other)
>(other)
==(other)
<=(other)
>=(other)
between?(other)

Он делает это, вызывая <=>(other) и возвращая правильный результат.

"instance <=> other" возвращает 0, если оба объекта равны, меньше 0, если instance больше other, и больше 0, если other больше.

5 голосов
/ 13 марта 2013

Я просто использовал Python Mixin для реализации модульного тестирования Python Milters. Как правило, milter разговаривает с MTA, что затрудняет юнит-тестирование. Тестовый миксин переопределяет методы, которые общаются с MTA, и вместо этого создает моделируемую среду, управляемую тестовыми примерами.

Итак, вы берете немодифицированное приложение milter, такое как spfmilter, и mixin TestBase, например:

class TestMilter(TestBase,spfmilter.spfMilter):
  def __init__(self):
    TestBase.__init__(self)
    spfmilter.config = spfmilter.Config()
    spfmilter.config.access_file = 'test/access.db'
    spfmilter.spfMilter.__init__(self)

Затем используйте TestMilter в тестовых случаях для применения milter:

def testPass(self):
  milter = TestMilter()
  rc = milter.connect('mail.example.com',ip='192.0.2.1')
  self.assertEqual(rc,Milter.CONTINUE)
  rc = milter.feedMsg('test1',sender='good@example.com')
  self.assertEqual(rc,Milter.CONTINUE)
  milter.close()

http://pymilter.cvs.sourceforge.net/viewvc/pymilter/pymilter/Milter/test.py?revision=1.6&view=markup

5 голосов
/ 31 июля 2012

mixin дает возможность добавить функциональность в класс, т. Е. Вы можете взаимодействовать с методами, определенными в модуле, включив модуль в нужный класс. Хотя ruby ​​не поддерживает множественное наследование, но предоставляет mixin в качестве альтернативы для достижения этого.

Вот пример, который объясняет, как множественное наследование достигается с помощью mixin.

module A    # you create a module
    def a1  # lets have a method 'a1' in it
    end
    def a2  # Another method 'a2'
    end
end

module B    # let's say we have another module
    def b1  # A method 'b1'
    end
    def b2  #another method b2
    end
end

class Sample    # we create a class 'Sample'
    include A   # including module 'A' in the class 'Sample' (mixin)
    include B   # including module B as well

    def S1      #class 'Sample' contains a method 's1'
    end
end

samp = Sample.new    # creating an instance object 'samp'

# we can access methods from module A and B in our class(power of mixin)

samp.a1     # accessing method 'a1' from module A
samp.a2     # accessing method 'a2' from module A
samp.b1     # accessing method 'b1' from module B
samp.b2     # accessing method 'a2' from module B
samp.s1     # accessing method 's1' inside the class Sample
4 голосов
/ 06 декабря 2016

ОП упомянул, что он / она никогда не слышал о миксинах в C ++, возможно, потому, что они называются Curily Recurring Template Pattern (CRTP) в C ++. Также @Ciro Santilli отметил, что mixin реализован через абстрактный базовый класс в C ++. В то время как абстрактный базовый класс может использоваться для реализации mixin, это избыточное решение, поскольку функциональность виртуальной функции во время выполнения может быть достигнута с использованием шаблона во время компиляции без дополнительных затрат на поиск виртуальной таблицы во время выполнения.

Шаблон CRTP подробно описан здесь

Я преобразовал пример python в ответе @Ciro Santilli в C ++, используя шаблонный класс ниже:

    #include <iostream>
    #include <assert.h>

    template <class T>
    class ComparableMixin {
    public:
        bool operator !=(ComparableMixin &other) {
            return ~(*static_cast<T*>(this) == static_cast<T&>(other));
        }
        bool operator <(ComparableMixin &other) {
            return ((*(this) != other) && (*static_cast<T*>(this) <= static_cast<T&>(other)));
        }
        bool operator >(ComparableMixin &other) {
            return ~(*static_cast<T*>(this) <= static_cast<T&>(other));
        }
        bool operator >=(ComparableMixin &other) {
            return ((*static_cast<T*>(this) == static_cast<T&>(other)) || (*(this) > other));
        }
        protected:
            ComparableMixin() {}
    };

    class Integer: public ComparableMixin<Integer> {
    public:
     Integer(int i) {
         this->i = i;
     }
     int i;
     bool operator <=(Integer &other) {
         return (this->i <= other.i);
     }
     bool operator ==(Integer &other) {
         return (this->i == other.i);
     }
    };

int main() {

    Integer i(0) ;
    Integer j(1) ;
    //ComparableMixin<Integer> c; // this will cause compilation error because constructor is protected.
    assert (i < j );
    assert (i != j);
    assert (j >  i);
    assert (j >= i);

    return 0;
}

РЕДАКТИРОВАТЬ: Добавлен защищенный конструктор в ComparableMixin, так что он может быть только унаследован и не создан. Обновлен пример, чтобы показать, как защищенный конструктор будет вызывать ошибку компиляции при создании объекта ComparableMixin.

3 голосов
/ 23 марта 2011

Я читал, что у вас есть фон c #. Так что хорошей отправной точкой может быть смешанная реализация для .NET.

Возможно, вы захотите проверить проект codeplex на http://remix.codeplex.com/

Просмотрите ссылку на симпозиум lang.net, чтобы получить обзор. На странице кодплекса еще есть что-то о документации.

С уважением Стефан

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...