gpt4 book ai didi

c++ - 设计模式 : Should I use inheritance here?

转载 作者:行者123 更新时间:2023-11-28 04:19:54 25 4
gpt4 key购买 nike

简介/设置

我正在从事一个文本编辑器项目,目前我已经设置了一个有效的语法荧光笔。但我觉得我的设计方法不太适合可维护的代码。

这是语法高亮类的声明(不要担心前面有“Q”的特定语言类型;那些只是由 C++ 的 Qt 框架定义的):

class Highlighter : public QSyntaxHighlighter
{
Q_OBJECT

public:

Highlighter(QTextDocument *parent = nullptr) : QSyntaxHighlighter (parent) {}
virtual void addKeywords(QStringList keywords);
virtual void setKeywordFormat();
virtual void setClassPattern(QRegularExpression classPattern);
virtual void setClassFormat();
virtual void setFunctionPattern(QRegularExpression functionPattern);
virtual void setFunctionFormat();
virtual void setQuotePattern(QRegularExpression quotePattern);
virtual void setQuoteFormat();
virtual void setInlineCommentPattern(QRegularExpression inlineCommentPattern);
virtual void setInlineCommentFormat();
virtual void setBlockCommentStartPattern(QRegularExpression blockCommentStart);
virtual void setBlockCommentEndPattern(QRegularExpression blockCommentEnd);
virtual void setBlockCommentFormat();
virtual void addRule(QRegularExpression pattern, QTextCharFormat format);

protected:

virtual void highlightBlock(const QString &text) override;
virtual void highlightMultilineComments(const QString &text);

private:

struct HighlightingRule
{
QRegularExpression pattern;
QTextCharFormat format;
};

QVector<HighlightingRule> rules;

QRegularExpression blockCommentStart;
QRegularExpression blockCommentEnd;

QTextCharFormat keywordFormat;
QTextCharFormat classFormat;
QTextCharFormat inlineCommentFormat;
QTextCharFormat blockCommentFormat;
QTextCharFormat quoteFormat;
QTextCharFormat functionFormat;
};

考虑到继承,我将许多函数声明为虚函数。然而,我是否应该使用继承确实是这个问题的核心(稍后会详细介绍)。

此外, header 包含以下不属于该类的函数:

Highlighter *cHighlighter(QTextDocument *doc);
Highlighter *cppHighlighter(QTextDocument *doc);
Highlighter *javaHighlighter(QTextDocument *doc);
Highlighter *pythonHighlighter(QTextDocument *doc);

这些函数中的每一个都组装了相应类型的荧光笔。以下是函数定义:

/* Returns a Highlighter object specific to the C language and its grammar and syntax.
*/
Highlighter *cHighlighter(QTextDocument *doc)
{
QStringList keywords;

keywords << "\\bauto\\b" << "\\bbreak\\b" << "\\bcase\\b" << "\\bchar\\b" << "\\bconst\\b"
<< "\\bcontinue\\b" << "\\bdefault\\b" << "\\bdo\\b" << "\\bdouble\\b" << "\\belse\\b"
<< "\\benum\\b" << "\\bextern\\b" << "\\bfloat\\b" << "\\bfor\\b" << "\\bgoto\\b"
<< "\\bif\\b" << "\\bint\\b" << "\\blong\\b" << "\\bregister\\b" << "\\breturn\\b"
<< "\\bshort\\b" << "\\bsigned\\b" << "\\bsizeof\\b" << "\\bstatic\\b" << "\\bstruct\\b"
<< "\\bswitch\\b" << "\\btypedef\\b" << "\\bunion\\b" << "\\bunsigned\\b" << "\\bvoid\\b"
<< "\\bvolatile\\b" << "\\bwhile\\b";

QRegularExpression classPattern("\\b[A-Z_][a-zA-Z0-9_]*\\b");
QRegularExpression quotePattern("(\".*\")|('\\\\.')|('.{0,1}')");
QRegularExpression functionPattern("\\b[A-Za-z_][A-Za-z0-9_]*(?=\\()");
QRegularExpression inlineCommentPattern("//.*");
QRegularExpression blockCommentStart("/\\*");
QRegularExpression blockCommentEnd("\\*/");

Highlighter *highlighter = new Highlighter(doc);
highlighter->addKeywords(keywords);
highlighter->setClassPattern(classPattern);
highlighter->setQuotePattern(quotePattern);
highlighter->setFunctionPattern(functionPattern);
highlighter->setInlineCommentPattern(inlineCommentPattern);
highlighter->setBlockCommentStartPattern(blockCommentStart);
highlighter->setBlockCommentEndPattern(blockCommentEnd);

return highlighter;
}


/* Returns a Highlighter object specific to the C++ language and its grammar and syntax.
*/
Highlighter *cppHighlighter(QTextDocument *doc)
{
Highlighter *cLanguage = cHighlighter(doc);
QStringList cppOnlyKeywords;

cppOnlyKeywords << "\\basm\\b" << "\\bbool\\b" << "\\bcatch\\b" <<
"\\bclass\\b" << "\\bconst_cast\\b" << "\\bdelete\\b" <<
"\\bdynamic_cast\\b" << "\\bexplicit\\b" << "\\bfalse\\b" <<
"\\bfriend\\b" << "\\binline\\b" << "\\bmutable\\b" <<
"\\bnamespace\\b" << "\\bnew\\b" << "\\boperator\\b" <<
"\\bprivate\\b" << "\\bprotected\\b" << "\\bpublic\\b" <<
"\\breinterpret_cast\\b" << "\\bstatic_cast\\b" <<
"\\btemplate\\b" << "\\bthis\\b" << "\\bthrow\\b" <<
"\\btrue\\b" << "\\btry\\b" << "\\btypeid\\b" << "\\btypename\\b" <<
"\\bvirtual\\b" << "\\busing\\b" << "\\bwchar_t\\b";

cLanguage->addKeywords(cppOnlyKeywords);
return cLanguage;
}


/* Returns a Highlighter object specific to the Java language and its grammar and syntax.
*/
Highlighter *javaHighlighter(QTextDocument *doc)
{
QStringList keywords;

keywords << "\\babstract\\b" << "\\bassert\\b" << "\\bboolean\\b" << "\\bbreak\\b" << "\\bbyte\\b"
<< "\\bcase\\b" << "\\bcatch\\b" << "\\bchar\\b" << "\\bclass\\b" << "\\bconst\\b" << "\\bcontinue\\b"
<< "\\bdefault\\b" << "\\bdo\\b" << "\\bdouble\\b" << "\\belse\\b" << "\\benum\\b" << "\\bextends\\b"
<< "\\bfinal\\b" << "\\bfinally\\b" << "\\bfloat\\b" << "\\bfor\\b" << "\\bgoto\\b" << "\\bif\\b"
<< "\\bimplements\\b" << "\\bimport\\b" << "\\binstanceof\\b" << "\\bint\\b" << "\\binterface\\b"
<< "\\blong\\b" << "\\bnative\\b" << "\\bnew\\b" << "\\bpackage\\b" << "\\bprivate\\b" << "\\bprotected\\b"
<< "\\bpublic\\b" << "\\breturn\\b" << "\\bshort\\b" << "\\bstatic\\b" << "\\bstrictfp\\b" << "\\bsuper\\b"
<< "\\bswitch\\b" << "\\bsynchronized\\b" << "\\bthis\\b" << "\\bthrow\\b" << "\\bthrows\\b" << "\\btransient\\b"
<< "\\btry\\b" << "\\bvoid\\b" << "\\bvolatile\\b" << "\\bwhile\\b" << "\\btrue\\b" << "\\bfalse\\b" << "\\bnull\\b";

QRegularExpression classPattern("\\b[A-Z_][a-zA-Z0-9_]*\\b");
QRegularExpression quotePattern("(\".*\")|('\\\\.')|('.{0,1}')");
QRegularExpression functionPattern("\\b[A-Za-z_][A-Za-z0-9_]*(?=\\()");
QRegularExpression inlineCommentPattern("//.*");
QRegularExpression blockCommentStart("/\\*");
QRegularExpression blockCommentEnd("\\*/");

Highlighter *highlighter = new Highlighter(doc);
highlighter->addKeywords(keywords);
highlighter->setClassPattern(classPattern);
highlighter->setQuotePattern(quotePattern);
highlighter->setFunctionPattern(functionPattern);
highlighter->setInlineCommentPattern(inlineCommentPattern);
highlighter->setBlockCommentStartPattern(blockCommentStart);
highlighter->setBlockCommentEndPattern(blockCommentEnd);

return highlighter;
}


/* Returns a Highlighter object specific to the Python language and its grammar and syntax.
*/
Highlighter *pythonHighlighter(QTextDocument *doc)
{
QStringList keywords;

keywords << "\\band\\b" << "\\bas\\b" << "\\bassert\\b" << "\\bbreak\\b" << "\\bclass\\b" << "\\bcontinue\\b"
<< "\\bdef\\b" << "\\bdel\\b" << "\\belif\\b" << "\\belse\\b" << "\\bexcept\\b" << "\\bFalse\\b"
<< "\\bfinally\\b" << "\\bfor\\b" << "\\bfrom\\b" << "\\bglobal\\b" << "\\bif\\b" << "\\bimport\\b"
<< "\\bin\\b" << "\\bis\\b" << "\\blambda\\b" << "\\bNone\\b" << "\\bnonlocal\\b" << "\\bnot\\b"
<< "\\bor\\b" << "\\bpass\\b" << "\\braise\\b" << "\\breturn\\b" << "\\bTrue\\b" << "\\btry\\b"
<< "\\bwhile\\b" << "\\bwith\\b" << "\\byield\\b";

QRegularExpression classPattern("\\b[A-Z_][a-zA-Z0-9_]*\\b");
QRegularExpression quotePattern("(\".*\")|('.*')");
QRegularExpression functionPattern("\\b[A-Za-z_][A-Za-z0-9_]*(?=\\()");
QRegularExpression inlineCommentPattern("#.*");
QRegularExpression blockCommentStart("'''");
QRegularExpression blockCommentEnd("'''");

Highlighter *highlighter = new Highlighter(doc);
highlighter->addKeywords(keywords);
highlighter->setClassPattern(classPattern);
highlighter->setQuotePattern(quotePattern);
highlighter->setFunctionPattern(functionPattern);
highlighter->setInlineCommentPattern(inlineCommentPattern);
highlighter->setBlockCommentStartPattern(blockCommentStart);
highlighter->setBlockCommentEndPattern(blockCommentEnd);

return highlighter;
}

问题

注意名为 highlightMultilineComments 的 protected 方法。默认情况下,由于 Qt 中语法突出显示的执行方式,此方法假定突出显示器的 blockCommentStartblockCommentEnd 正则表达式不相同。对于像 Python 这样的语言,情况显然不是这样,因为开始和结束注释分隔符是相同的(三重单引号或双引号)。在这种情况下,函数不会按预期执行。这就是您需要知道的全部内容。

继承问题

我将 highlightMultilineComments 方法设为虚拟方法,目的是创建一个子类,比如 PythonHighlighter,它只覆盖定义自定义逻辑的特定函数。理论上,其他语言可以覆盖所有内容并自定义他们希望如何设置荧光笔(如果我使用继承)。

但是,如果我要为 Python 创建一个子类,那就意味着我必须为 C、C++、Java 和我想在将来添加的任何其他语言创建一个子类(为了保持一致性)。这显然比我目前的方法更难管理,我目前的方法只有组装荧光笔的功能。如果我为每种语言添加一个类,源文件的数量将显着增加。

构建器函数的问题

所以使用构建器函数有它的好处。但是这种方法不允许我覆盖 highlightMultilineComments 方法。所以在这方面显然不理想。

问题

我如何利用继承的好处——能够根据语言覆盖 highlightMultilineComments 等方法——而不牺牲“构建器函数”的相对可维护性?

我考虑过的其他事项

我还考虑过添加类似 highlightSymmetricMultilineComments 的功能。然后,highlightMultilineComments 可以检查 blockCommentStartblockCommentEnd 是否具有相同的正则表达式模式。如果它们确实具有相同的模式,该函数将简单地调用其对称变体。

这提出了一个明显的问题——考虑到并非所有语言都具有对称的多行注释(Python 是目前唯一受文本编辑器支持的语言),将它放在 Highlighter 中是没有意义的。

最佳答案

考虑添加一个 commentHighlighter 成员变量来表示执行实际突出显示的函数:

std::function<void(Highlighter&, const QString&)> commentHighlighter;

然后我们可以编写 highlightMultilineComments 以便它调用这个成员变量:

void highlightMultilineComments(const QString &text) 
{
// If the class has a valid commentHighlighter, use that
if(commentHighlighter)
{
commentHighlighter(*this, text);
}
else //Otherwise, use the default implementation
{
// Default implementation
}
}

如果您需要一种语言的专门高亮显示,那么您可以只提供一个函数来进行高亮显示,而不必为其创建一个新类。

关于c++ - 设计模式 : Should I use inheritance here?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55697892/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com