В Okio мы объявляем два дополнительных набора источников, nativeMain
и nativeTest
, и настраиваем встроенные исходные наборы источников в зависимости от них:
apply plugin: 'org.jetbrains.kotlin.multiplatform'
kotlin {
iosX64()
iosArm64()
linuxX64()
macosX64()
mingwX64('winX64')
sourceSets {
nativeMain {
dependsOn commonMain
}
nativeTest {
dependsOn commonTest
}
configure([iosX64Main, iosArm64Main, linuxX64Main, macosX64Main, winX64Main]) {
dependsOn nativeMain
}
configure([iosX64Test, iosArm64Test, linuxX64Test, macosX64Test, winX64Test]) {
dependsOn nativeTest
}
}
}
Вот как я бы реализовал класс:
template<class PenType>
class Writer
{
public:
Writer(const PenType& pen = PenType()) : pen(pen) {}
void StartWriting()
{
pen.Write();
}
private:
PenType pen;
};
Это позволяет пользователю передать конкретный объект Pen в конструктор, если он либо не имеет конструктора по умолчанию, либо вы не хотите, чтобы он использовался, и, во-вторых, он по-прежнему позволяет вам опускать объект PenType, если вы счастливы позволить ему создать его с помощью конструктора по умолчанию. Стандартная библиотека C ++ делает то же самое для многих классов (подумайте, например, о распределителях для контейнерных классов).
Я удалил наследование. На самом деле, похоже, что он ничего не добавляет (и может вызвать проблемы. Вероятно, вы не хотите, чтобы пользователь класса Writer напрямую вызывал функцию PenType :: Write. Вместо этого вы можете использовать частное наследование, но часто композиция представляет собой более простой и традиционный дизайн.
В общем, дизайн на основе политик не требует наследования. Добавление его в качестве участника также работает. Если вы все же выбираете наследование, сделайте его частным, чтобы не получить проблему, о которой вы упомянули как №4.
Это выглядит как хороший пример реализации интеллектуального указателя на основе политик: ссылка . Андрей Александреску описывает реализацию интеллектуального указателя на основе политик в одной из своих книг. Теперь что касается ваших вопросов. У меня есть некоторый опыт в этом вопросе, но его недостаточно, чтобы принимать мои слова как должное:
Ad 1 & 4. Я полагаю, что дизайн на основе политик больше связан с шаблонами, чем наследованием. Вы пишете класс шаблона, а аргументы шаблона - это классы политики, например:
template<class FooPolicy, class BarPolicy>
class Baz {
// implementation goes here
};
Затем вы используете методы из классов политики в своем классе:
void Baz::someMethod(int someArg) {
FooPolicy::methodInit();
// some stuff
BarPolicy::methodDone();
}
Я использую статические методы в этом примере, потому что часто политика не требует какого-либо состояния. Если это так, вы включаете состояние политики по составу, а не по наследованию:
template<class FooPolicy, class BarPolicy>
class Baz {
private:
FooPolicy::State fooState; // might require 'typename' keyword, I didn't
// actually tried this in any compiler
// rest of the Baz class
};
Ad 2. Вы можете написать специализацию шаблона - для определенной комбинации основного класса и его '
1 - Эта реализация выглядит верный? Я имею в виду, действительно ли это выглядит как дизайн на основе политик?
Классы политик получают свою полезность от комбинирования поведений для создания разнообразных комбинаций. Когда у вас есть один такой параметр шаблона, это не совсем класс политики.
2 - Теперь я могу прикрепить любые ручки к писатель. Но что я буду делать, когда получу ручка без конструктора по умолчанию (только параметризованные конструкторы)? Как справлюсь ли я с этой ситуацией?
Опять же, это странный пример класса политики.Однако, чтобы напрямую ответить на ваш вопрос, вы можете предоставить конструктор, который принимает PenType. Вероятно, вам также следует избегать наследования от PenType и вместо этого хранить его как член (нет необходимости тесно связывать ваш класс политики с его политиками).
Думаю, компилятор заменит PenType с помощью InkPen. Если да, то почему я не умею для вызова просто Write () из StartWriting () вместо префикса имя базового класса (PenType :: Write ())?
Когда вы наследуете от шаблона класса, вы должны указать this-> member или BaseClass :: member.
4 - Я считаю, что проектные силы, основанные на политике вы должны уйти из классов, что является семантически недопустимый. В приведенном выше код, писатель происходит от пера только потому, что писатель пользуется пером. Но говоря, что писатель - это ручка, семантически неверный. Есть ли другой способ лучше? чтобы решить эту проблему, или мне не хватает что-то здесь?
Сохраните PenType как член, как предложено выше. Всегда предпочитайте композицию наследованию, поскольку она позволяет избежать тесных взаимосвязей наследования.