我不明白为什么在 base class 中测试可能的接口是错误的
I don't understand why it is wrong to test for possible interfaces in a base class
我有一个抽象基础 class,它将在数百个派生 class 中使用,包括一个额外的抽象 class.
至少有 2 个属性(我们称它们为 Purpose 和 Description,都是字符串)将被添加到许多(但不是全部)具体派生的 classes 中,所以我创建了接口(IPurposeful和 IDescribable)以在需要时添加它们。目前一切顺利。
我想要一个单一的方法,我可以调用所有从我的基础 class 派生的 classes 来验证和更新描述 属性 如果它确实是可描述的,或者如果它不是 IDesribable,则 return 为真。我想要另一个与 validate/update 目的 属性.
类似的方法
我使用基础 class 中的一个方法实现了这一点,看起来像这样:
protected bool CheckDescription(bool modify = false)
{
if (this is IDescribable ele)
{
var newDesc = GetCorrectDescription();
UpdateDescription(newDesc, ele.Description, modify);
return newDesc.Equals(ele.Description);
}
else
{
return true;
}
}
SonarQube 将 "this is IDescribable" 检查标记为阻止程序(错误做法),我想知道为什么?我能想到的复制此功能的唯一其他方法是将基本方法更改为:
protected virtual bool CheckDescription(bool modify = false)
{
return true;
}
然后将这个完全相同的方法添加到可能派生的数百个 classes:
protected override bool CheckDescription(bool modify = false)
{
var newDesc = GetCorrectDescription();
UpdateDescription(newDesc, Description, modify);
return newDesc.Equals(Description);
}
现在这似乎是不好的做法。
编辑:更改了 is/as 模式以删除冗余
如果你的class可能是IDescribable
并且可能是IPurposeful
,那么给出它 合理的默认实现 这些接口可能是无操作的,并允许您的后代 classes 根据需要覆盖这些实现。
不需要类型检查。只需调用可覆盖的方法并遵守它们的结果。
如果您的 "optional" 接口不允许合理的空操作实现,请重新访问它们的定义。
现在您的基础 class 可以依赖接口,而不是测试它们。
您可能会在此处引入运行时错误 - 但对于需要实现特定接口且编译时不可检查的基本 class 方法也是如此。
我决定进一步探索扩展方法,发现它们可以满足我的特殊需求。我想标记将扩展方法视为正确答案的原始建议,但似乎找不到这样做的机制。
无论如何,扩展方法满足我的要求,能够在一个地方为大多数派生 类 定义默认算法,并仅在特定派生 类 中覆盖该行为 if/when .
缺点之一是我无法从 "override" 方法中调用 "base" 实现。这可能会导致将来需要重复代码,但幸运的是现在我还没有遇到这个问题。
我有一个抽象基础 class,它将在数百个派生 class 中使用,包括一个额外的抽象 class.
至少有 2 个属性(我们称它们为 Purpose 和 Description,都是字符串)将被添加到许多(但不是全部)具体派生的 classes 中,所以我创建了接口(IPurposeful和 IDescribable)以在需要时添加它们。目前一切顺利。
我想要一个单一的方法,我可以调用所有从我的基础 class 派生的 classes 来验证和更新描述 属性 如果它确实是可描述的,或者如果它不是 IDesribable,则 return 为真。我想要另一个与 validate/update 目的 属性.
类似的方法我使用基础 class 中的一个方法实现了这一点,看起来像这样:
protected bool CheckDescription(bool modify = false)
{
if (this is IDescribable ele)
{
var newDesc = GetCorrectDescription();
UpdateDescription(newDesc, ele.Description, modify);
return newDesc.Equals(ele.Description);
}
else
{
return true;
}
}
SonarQube 将 "this is IDescribable" 检查标记为阻止程序(错误做法),我想知道为什么?我能想到的复制此功能的唯一其他方法是将基本方法更改为:
protected virtual bool CheckDescription(bool modify = false)
{
return true;
}
然后将这个完全相同的方法添加到可能派生的数百个 classes:
protected override bool CheckDescription(bool modify = false)
{
var newDesc = GetCorrectDescription();
UpdateDescription(newDesc, Description, modify);
return newDesc.Equals(Description);
}
现在这似乎是不好的做法。
编辑:更改了 is/as 模式以删除冗余
如果你的class可能是IDescribable
并且可能是IPurposeful
,那么给出它 合理的默认实现 这些接口可能是无操作的,并允许您的后代 classes 根据需要覆盖这些实现。
不需要类型检查。只需调用可覆盖的方法并遵守它们的结果。
如果您的 "optional" 接口不允许合理的空操作实现,请重新访问它们的定义。
现在您的基础 class 可以依赖接口,而不是测试它们。
您可能会在此处引入运行时错误 - 但对于需要实现特定接口且编译时不可检查的基本 class 方法也是如此。
我决定进一步探索扩展方法,发现它们可以满足我的特殊需求。我想标记将扩展方法视为正确答案的原始建议,但似乎找不到这样做的机制。
无论如何,扩展方法满足我的要求,能够在一个地方为大多数派生 类 定义默认算法,并仅在特定派生 类 中覆盖该行为 if/when .
缺点之一是我无法从 "override" 方法中调用 "base" 实现。这可能会导致将来需要重复代码,但幸运的是现在我还没有遇到这个问题。