如何在复合 C# 中继承多个叶部分?
How to inherit multiple leaf parts in composite c#?
我正在用 c# 编写项目,其中包括不止一片叶子,我想知道这些节点是否应该继承复合而不是抽象 class。所以我有三片叶子:
- 段落
- 段落组
- 文档
段落继承抽象的文本 class class。现在,段落组 class 继承了段落 class,文档继承了段落组和段落。所以我想知道哪个 class 应该是我的复合材料?我正在考虑将复合材料放在 ParagraphComposite.cs class 中,然后使其看起来像这样:
段落和段落复合继承抽象class文本和段落组和文档继承段落复合class。
这是正确的做法吗?任何反馈将不胜感激。
让我们假设所有这些 class 都有共同的属性,例如 Text
属性,但也有不同的属性,例如其他类型的集合。为了不与Text
属性冲突,我将抽象基称为classTextBase
.
其他 classes 应该派生自 TextBase
。例如。 Document
文档会有一个 ParagraphGroups
集合,但没有 Paragraphs
集合。即,它不能从具有 Paragraphs
集合的 ParagraphGroup
派生。
可能的方法:
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
class不继承ParagraphGroup
。相反,它包含 ParagraphGroup
的集合。为了简单起见,我使用了数组,但您也可以使用 List<T>
或创建您自己的特定集合类型。
注意当你获取或设置[=21=的Text
属性时,这会递归调用[=24=的Text
属性 ] 和 Paragraph
,以便递归地连接或拆分元素。
您将获得文档中的第一行文本
string firstLine = document.ParagraphGroups[0].Paragraphs[0].Lines[0];
您将 Add
或 Remove
之类的方法放在哪里?
一种可能是简单地依赖于您正在使用的集合的相应方法。示例:如果您正在使用 List<T>
集合,您可以简单地使用 List Methods(示例 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>
作为 Lines
属性。Paragraph
将实现 ITextCollection<string>
public void Add(string item)
{
Lines.Add(item);
}
public void RemoveAt(int i)
{
Lines.RemoveAt(i);
}
请注意,其他类型的实现方式不同,因为它们的集合名称不同并且属于另一种类型。例如。 ParagraphGroup
将实现 ITextCollection<Paragraph>
并且必须在 Paragraphs
集合中添加和删除。
这使您的 classes 成为复合体,因为它们本身不实现集合功能的细节,而是包含一个集合并将操作委托给这些集合。
我正在用 c# 编写项目,其中包括不止一片叶子,我想知道这些节点是否应该继承复合而不是抽象 class。所以我有三片叶子:
- 段落
- 段落组
- 文档
段落继承抽象的文本 class class。现在,段落组 class 继承了段落 class,文档继承了段落组和段落。所以我想知道哪个 class 应该是我的复合材料?我正在考虑将复合材料放在 ParagraphComposite.cs class 中,然后使其看起来像这样:
段落和段落复合继承抽象class文本和段落组和文档继承段落复合class。
这是正确的做法吗?任何反馈将不胜感激。
让我们假设所有这些 class 都有共同的属性,例如 Text
属性,但也有不同的属性,例如其他类型的集合。为了不与Text
属性冲突,我将抽象基称为classTextBase
.
其他 classes 应该派生自 TextBase
。例如。 Document
文档会有一个 ParagraphGroups
集合,但没有 Paragraphs
集合。即,它不能从具有 Paragraphs
集合的 ParagraphGroup
派生。
可能的方法:
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
class不继承ParagraphGroup
。相反,它包含 ParagraphGroup
的集合。为了简单起见,我使用了数组,但您也可以使用 List<T>
或创建您自己的特定集合类型。
注意当你获取或设置[=21=的Text
属性时,这会递归调用[=24=的Text
属性 ] 和 Paragraph
,以便递归地连接或拆分元素。
您将获得文档中的第一行文本
string firstLine = document.ParagraphGroups[0].Paragraphs[0].Lines[0];
您将 Add
或 Remove
之类的方法放在哪里?
一种可能是简单地依赖于您正在使用的集合的相应方法。示例:如果您正在使用 List<T>
集合,您可以简单地使用 List Methods(示例 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>
作为 Lines
属性。Paragraph
将实现 ITextCollection<string>
public void Add(string item)
{
Lines.Add(item);
}
public void RemoveAt(int i)
{
Lines.RemoveAt(i);
}
请注意,其他类型的实现方式不同,因为它们的集合名称不同并且属于另一种类型。例如。 ParagraphGroup
将实现 ITextCollection<Paragraph>
并且必须在 Paragraphs
集合中添加和删除。
这使您的 classes 成为复合体,因为它们本身不实现集合功能的细节,而是包含一个集合并将操作委托给这些集合。