C# - 在子 classes 中调用个别行为后,在抽象 class 中添加公共行为
C# - Add common behaviour in abstract class after calling individual behaviours in subclasses
我对抽象 classes 很陌生。通常你可以在 base-class 中创建一个成员,然后通过使用 base.Member
在 subclass 中调用它来扩展它的逻辑。但是我可以反过来做吗?
我有一个 abstract class A
和 属性 类型 IEnumerable<T>
:
abstract class A
{
IEnumerable<int> Foo { get; }
}
我希望 A 的派生 classes 到 return 一个单独的 IEnumerable,并希望在相同条件下使用 .Where
"filter" 它们。我做了以下操作:
abstract class A
{
public IEnumerable<int> Foo => Bar.Where(x => true);
protected abstract IEnumerable<int> Bar { get; }
}
abstract class B : A
{
protected override IEnumerable<int> Bar {
get { yield return 1; }
}
}
它有效,但这是正确的方法吗?或者我可以只使用一个 属性 来做同样的事情吗?如果我有一些 classes 之间还必须过滤它,感觉特别笨拙,因为我只需要根据我拥有的层数添加越来越多的成员。
这个方法就好了。
您有一个符合 DRY 原则的基础 class 中所有派生的 classes (.Where()
) 共有的行为。
那么在那些 classes 中,每个派生的 class 都有特定的行为。
It feels especially clunky if I have some classes between which also
have to filter it because I'd just have to add more and more members
based on the amount of layers I have.
好吧,如果你需要对不同的情况有不同的逻辑,那就太好了。
这是一个非常标准的成语。
这样考虑:在定义抽象 Bar
时,您说的是 "all implementations can 'Bar'",然后当您从 Foo
调用它时,这是完美的,因为所有实现都可以 'Bar'.
It feels especially clunky if I have some classes between which also have to filter it because I'd just have to add more and more members based on the amount of layers I have.
您的意思是其他 类 也在对同一个可枚举对象执行 Where()
吗?别介意; A
做的是 Foo
的意思,子类做的是 Bar
的意思,不管是不是另一个 Where()
在 A
。 (有时我们确实必须打破这个规则,如果它被证明是一个性能热点,但首先初始设计不是考虑这一点的地方,其次 Enumerable.Where()
实际上已经针对 [的顺序调用进行了优化=12=] 关于 Where()
的结果)。
你这里的实际上是 Template Method Pattern。当您有多个受保护的抽象方法时,这尤其适用,其中抽象 class 控制这些方法的流程。
对于你正在努力做的事情,很好,你想留着就留着。但是,这不是唯一的解决方案。
当您只有 1 种方法时,有时建议注入一个对象来做这 1 件事。这更容易扩展,因为对于每个新的 B
你只需要测试它的细节,而不是抽象的部分。
最后,我觉得你的情况最适合The Decorator Pattern。
class B
{
public IEnumerable<int> Foo => yield return 1;
}
class A : B
{
private B b;
public IEnumerable<int> Foo => b.Foo.Where(x => true);
public A(B b)
{
this.b = b;
}
}
这有点简化,您可能需要 A
和 B
都实现的实际接口。当您谈论添加其他 class 过滤器时,这确实可以很好地扩展。然后可以实例化您的 classes 以执行您想要的过滤。
我对抽象 classes 很陌生。通常你可以在 base-class 中创建一个成员,然后通过使用 base.Member
在 subclass 中调用它来扩展它的逻辑。但是我可以反过来做吗?
我有一个 abstract class A
和 属性 类型 IEnumerable<T>
:
abstract class A
{
IEnumerable<int> Foo { get; }
}
我希望 A 的派生 classes 到 return 一个单独的 IEnumerable,并希望在相同条件下使用 .Where
"filter" 它们。我做了以下操作:
abstract class A
{
public IEnumerable<int> Foo => Bar.Where(x => true);
protected abstract IEnumerable<int> Bar { get; }
}
abstract class B : A
{
protected override IEnumerable<int> Bar {
get { yield return 1; }
}
}
它有效,但这是正确的方法吗?或者我可以只使用一个 属性 来做同样的事情吗?如果我有一些 classes 之间还必须过滤它,感觉特别笨拙,因为我只需要根据我拥有的层数添加越来越多的成员。
这个方法就好了。
您有一个符合 DRY 原则的基础 class 中所有派生的 classes (.Where()
) 共有的行为。
那么在那些 classes 中,每个派生的 class 都有特定的行为。
It feels especially clunky if I have some classes between which also have to filter it because I'd just have to add more and more members based on the amount of layers I have.
好吧,如果你需要对不同的情况有不同的逻辑,那就太好了。
这是一个非常标准的成语。
这样考虑:在定义抽象 Bar
时,您说的是 "all implementations can 'Bar'",然后当您从 Foo
调用它时,这是完美的,因为所有实现都可以 'Bar'.
It feels especially clunky if I have some classes between which also have to filter it because I'd just have to add more and more members based on the amount of layers I have.
您的意思是其他 类 也在对同一个可枚举对象执行 Where()
吗?别介意; A
做的是 Foo
的意思,子类做的是 Bar
的意思,不管是不是另一个 Where()
在 A
。 (有时我们确实必须打破这个规则,如果它被证明是一个性能热点,但首先初始设计不是考虑这一点的地方,其次 Enumerable.Where()
实际上已经针对 [的顺序调用进行了优化=12=] 关于 Where()
的结果)。
你这里的实际上是 Template Method Pattern。当您有多个受保护的抽象方法时,这尤其适用,其中抽象 class 控制这些方法的流程。
对于你正在努力做的事情,很好,你想留着就留着。但是,这不是唯一的解决方案。
当您只有 1 种方法时,有时建议注入一个对象来做这 1 件事。这更容易扩展,因为对于每个新的 B
你只需要测试它的细节,而不是抽象的部分。
最后,我觉得你的情况最适合The Decorator Pattern。
class B
{
public IEnumerable<int> Foo => yield return 1;
}
class A : B
{
private B b;
public IEnumerable<int> Foo => b.Foo.Where(x => true);
public A(B b)
{
this.b = b;
}
}
这有点简化,您可能需要 A
和 B
都实现的实际接口。当您谈论添加其他 class 过滤器时,这确实可以很好地扩展。然后可以实例化您的 classes 以执行您想要的过滤。