diff --git a/include/links/LeafLink.h b/include/links/LeafLink.h index 1f2a95d..8a1d8a8 100644 --- a/include/links/LeafLink.h +++ b/include/links/LeafLink.h @@ -3,10 +3,14 @@ #include /// \brief Связь для листового узла, не допускающая дочерних элементов. -class LeafLink : public BaseLink { +template +class LeafLink : public BaseLink { public: - using BaseLink::BaseLink; - void addChild(const NodePtr&) override { - throw std::logic_error("LeafLink cannot have children"); + using ElemPtr = std::shared_ptr; + + LeafLink(std::shared_ptr e) : BaseLink(e) {} + + void addChild(const ElemPtr&) override { + throw std::logic_error("Leaf cannot have children"); } }; diff --git a/include/mixins/HierarchicalLinkMixin.h b/include/mixins/HierarchicalLinkMixin.h index bdb15d8..c2a1d0b 100644 --- a/include/mixins/HierarchicalLinkMixin.h +++ b/include/mixins/HierarchicalLinkMixin.h @@ -1,20 +1,21 @@ #pragma once #include -#include "mixins/LazyLinkMixin.h" #include + +#include "ifaces/INode.h" +#include "mixins/LazyLinkMixin.h" #include "links/OneToManyLink.h" #include "links/OneToOneLink.h" #include "Logger.h" /// \brief Миксин для иерархических связей между элементами. -/// \tparam TElem Тип дочернего элемента. +/// \tparam INode Тип дочернего элемента. /// Автоматически выбирает тип связи (один-ко-многим или один-к-одному) в зависимости от типа /// дочернего узла. Если тип дочернего узла совпадает с родителем, то используется связь /// один-ко-многим. При попытке подключить узел отличного типа выбирается связь один-к-одному. -template -class HierarchicalLinkMixin : public LazyLinkMixin> { - using LinkPtr = std::shared_ptr>; - using ElemPtr = std::shared_ptr; +class HierarchicalLinkMixin : public LazyLinkMixin> { + using LinkPtr = std::shared_ptr>; + using ElemPtr = std::shared_ptr; public: ~HierarchicalLinkMixin() override { @@ -23,7 +24,7 @@ public: void linkChild(const ElemPtr& child) override { hierarchicalInit(child); - LazyLinkMixin>::linkChild(child); + LazyLinkMixin>::linkChild(child); } protected: @@ -36,10 +37,10 @@ protected: if (typeid(*child) == typeid(*this)) { Logger::get("Mixin").dbg("--- Mutate to OneToMany"); - newLink = std::make_shared>(*this); + newLink = std::make_shared>(*this); } else { Logger::get("Mixin").dbg("--- Mutate to OneToOne"); - newLink = std::make_shared>(*this); + newLink = std::make_shared>(*this); } if (newLink && this->link_) diff --git a/include/nodes/ComplexNode.h b/include/nodes/ComplexNode.h index f36f3c9..2109ed5 100644 --- a/include/nodes/ComplexNode.h +++ b/include/nodes/ComplexNode.h @@ -8,7 +8,7 @@ /// \brief Класс сложного (составного) узла дерева. /// Может содержать несколько дочерних ComplexNode или один SimpleNode. class ComplexNode : public BaseNode, - virtual public HierarchicalLinkMixin, + virtual public HierarchicalLinkMixin, public FabricMixin { public: ~ComplexNode() { diff --git a/include/nodes/LeafNode.h b/include/nodes/LeafNode.h new file mode 100644 index 0000000..0372658 --- /dev/null +++ b/include/nodes/LeafNode.h @@ -0,0 +1,23 @@ +#pragma once + +#include "nodes/BaseNode.h" +#include "mixins/LazyLinkMixin.h" +#include "mixins/FabricMixin.h" +#include "links/LeafLink.h" +#include "Logger.h" + +/// \brief Класс простого (листового) узла дерева. +/// Может содержать только одного дочернего ComplexNode. +class LeafNode : public BaseNode, + virtual public LazyLinkMixin>, + public FabricMixin { +public: + ~LeafNode() { + Logger::get("ConDes").dbg(std::string("--- Leaf destructor called for: ") + name_); + } +private: + friend class FabricMixin; + LeafNode(std::string name) : BaseNode(std::move(name)) { + Logger::get("ConDes").dbg(std::string("--- Leaf constructor called for: ") + name_); + } +}; diff --git a/src/main.cpp b/src/main.cpp index 2feb4e3..56eb965 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,6 +4,7 @@ #include "nodes/SimpleNode.h" #include "nodes/ComplexNode.h" +#include "nodes/LeafNode.h" #include "iterators/Traversal.h" @@ -58,9 +59,18 @@ int main() { auto child3 = ComplexNode::create("ComplexChild3"); root->linkChild(child3); - child3->linkChild(SimpleNode::create("SimpleSubChild3")); + auto leaf3 = LeafNode::create("LeafSubChild3"); + child3->linkChild(leaf3); { + // Негативный сценарий 0: попытка добавить SimpleNode к LeafNode + try { + leaf3->linkChild(SimpleNode::create("ShouldFail")); + logger.err("[ERROR] Не должно было получиться добавить SimpleNode к LeafNode!"); + } catch (const std::logic_error& e) { + logger.warn(std::string("[Ожидаемое исключение] ") + e.what()); + } + // Негативный сценарий 1: попытка добавить второй SimpleNode к ComplexNode try { child2->linkChild(SimpleNode::create("ShouldFail"));