c# - 如何在复合 C# 中继承多个叶子部分?
问题描述
我正在用 C# 编写项目,其中包含不止一个叶子,我想知道这些节点是否应该继承复合而不是抽象类。所以我有三片叶子:
- 段落
- 段落组
- 文档
段落继承文本类,它是抽象类。现在,Group of Paragraphs 类继承了 Paragraph 类,而 Document 继承了 Group of Paragraphs 和 Paragraphs。所以我想知道哪个类应该是我的复合材料?我正在考虑将复合材料放在 ParagraphComposite.cs 类中,然后让它看起来像这样:
Paragraph 和 ParagraphComposite 继承抽象类 text 和 Group of Paragraphs 和 Document 继承 ParagraphComposite 类。
这是正确的方法吗?任何反馈将不胜感激。
解决方案
让我们假设所有这些类都具有共同的属性,例如Text
属性,但也有不同的属性,例如其他类型的集合。为了不与Text
属性冲突,我将调用抽象基类TextBase
。
其他类应派生自TextBase
. 例如,Document
文档将有一个ParagraphGroups
集合,但没有一个Paragraphs
集合。即,它不能派生自ParagraphGroup
哪一个Paragraphs
集合。
可能的方法:
public abstract class TextBase
{
public const string LineSeparator = "\n";
public const string ParagraphSeparator = "\r";
public const string ParagraphGroupSeparator = "\v";
public abstract string Text { get; set; }
}
public class Paragraph : TextBase
{
public string[] Lines { get; set; } = new string[0];
public override string Text
{
get => String.Join(LineSeparator, Lines);
set => Lines = value.Split(new string[] { LineSeparator }, StringSplitOptions.None);
}
}
public class ParagraphGroup : TextBase
{
public Paragraph[] Paragraphs { get; set; } = new Paragraph[0];
public override string Text
{
get => String.Join(ParagraphSeparator, Paragraphs.Select(p => p.Text));
set => Paragraphs =
value.Split(new string[] { ParagraphSeparator }, StringSplitOptions.None)
.Select(s => new Paragraph { Text = s })
.ToArray();
}
}
public class Document : TextBase
{
public ParagraphGroup[] ParagraphGroups { get; set; } = new ParagraphGroup[0];
public override string Text
{
get => String.Join(ParagraphGroupSeparator, ParagraphGroups.Select(g => g.Text));
set => ParagraphGroups =
value.Split(new string[] { ParagraphGroupSeparator }, StringSplitOptions.None)
.Select(s => new ParagraphGroup { Text = s })
.ToArray();
}
}
该类Document
不继承ParagraphGroup
。相反,它包含一个ParagraphGroup
. 为了简单起见,我使用了数组,但您也可以使用List<T>
或创建自己的特定集合类型。
请注意,当您获取或设置 的Text
属性时Document
,这会递归调用 and 的属性Text
,以便递归地连接或拆分元素。ParagraphGroup
Paragraph
您将获得文档中的第一行文本
string firstLine = document.ParagraphGroups[0].Paragraphs[0].Lines[0];
你在哪里放置类似Add
or的方法Remove
?
一种可能性是简单地依赖您正在使用的集合的相应方法。示例:如果您使用的是List<T>
集合,则可以简单地使用列表方法(例如paragraph.Lines.Add("hello");
.
如果您想将这些方法直接添加到Document
等Paragraph
,您将面临其中一些将采用不同类型的参数的问题。你可以TextBase
通用,但你会失去分配的兼容性。最好声明一个泛型接口。例如
public interface ITextCollection<T>
{
public abstract void Add(T item);
public abstract void RemoveAt(int i);
}
一个可能的实现Paragraph
(假设您使用的是List<string>
forLines
属性。Paragraph
将实现ITextCollection<string>
public void Add(string item)
{
Lines.Add(item);
}
public void RemoveAt(int i)
{
Lines.RemoveAt(i);
}
请注意,其他类型的实现是不同的,因为它们的集合名称不同并且属于另一种类型。例如ParagraphGroup
,将实施ITextCollection<Paragraph>
并且必须从Paragraphs
集合中添加和删除。
这使得您的类组合起来,因为它们本身不实现集合功能的细节,而是包含一个集合并将操作委托给这些集合。
推荐阅读
- python - Pyppeteer - 单击链接后运行 page.content() 时出错
- java - 如何让我的星星旋转?我可以制作星星,但不知道如何让它旋转
- scala - Scala模式匹配与case语句
- r - R - 根据其他列的计算值选择数据框中的年份
- python - 如何重写这个函数
- python - 在 Python 类中使用 lambda 时的内存泄漏
- java - 如何按属性对arraylist对象进行分组?
- spring-boot - Spring数据按嵌套属性排序
- tensorflow - 如何在 Tensorflow 中标准化图像?
- python - python中opencv库的问题