C#: 抽象类中是否可以不实现 protected internal 抽象方法?

4
我需要在我的抽象基类中做哪些改动,以便在任何情况下只需要实现一个方法而不必同时实现两个方法?我的示例如下:
internal abstract class BaseBar<T> where T : BaseThing
{
    protected internal abstract T DataFromXmlElements(IEnumerable<XmlNode> nodes);
    protected internal abstract T DataFromXmlElements(IEnumerable<XmlNode> nodes, string[] fieldNames);
}

class FooBarMapper : BaseBar<FooData>
{
    protected internal override SforceObjectValueData DataObjectFromXmlElements(IEnumerable<XmlNode> nodes)
    {
        throw new NotImplementedException();
    }

    protected internal override FooData DataFromXmlElements(IEnumerable<XmlNode> nodes, string[] fieldNames)
    {
        FooData o = new FooData
        {
            bar1 = bar1,
            bar2 = bar2
        };
        return o;
    }
}

干杯。

编辑:我知道设计很奇怪/糟糕/愚蠢...我正在处理遗留代码,现在没有时间进行重构。 我正在尝试添加使用字符串数组的第二种方法。


我对这种设计有点不确定。使用对象组合会更好。 - ChaosPandion
一个内部的抽象类?这意味着它只能被继承,在FooBarMapper中也只能被继承,其他地方都无法继承。这有什么意义? - Robert Harvey
@Robert Harvey:也许它不需要从该程序集外派生。 - Colin Mackay
@Robert - 它只能从程序集内继承。 - ChaosPandion
哦,没事了。这里还太早了。 - Robert Harvey
9个回答

3
也许这对你有用?
internal abstract class BaseBar<T> where T : BaseThing
{
    protected internal abstract T DataFromXmlElements(IEnumerable<XmlNode> nodes, params string[] fieldNames);
}

根据他们的更新,这将破坏任何依赖于特定方法签名的代码。protected internal abstract T DataFromXmlElements(IEnumerable<XmlNode> nodes) - ChaosPandion
是的,你需要传递 null - hunter

2
你还可以将DataFromXmlElements的参数封装在一个类中,然后在编写实现时以一种优雅的方式检查该类的内容...

1
我猜你需要2或3个抽象类来实现这一点。
public interface BaseBar1<T> // does one
public interface BaseBar2<T> // does the other
public interface BaseBar3<T> // does both

你可以使用可选参数

internal abstract class BaseBar<T> where T : BaseThing
{
    protected internal abstract T DataFromXmlElements(
        IEnumerable<XmlNode> nodes, string[] fieldNames);
}

class FooBarMapper : BaseBar<FooData>
{
    protected internal override FooData DataFromXmlElements(
        IEnumerable<XmlNode> nodes, 
        [Optional] string[] fieldNames)
    {
        if (fieldNames == null) // skip stuff
        else // do stuff
    }

更多关于可选属性的内容。


1

必须实现抽象成员,所以我想没有绕过的方法。

另一个解决方案是定义两个接口,每个接口包含要实现的一个成员。然后实现类可以实现一个或两个接口。

例如:

public interface BaseBarA<T> where T : BaseThing{
  protected internal abstract T DataFromXmlElements(IEnumerable<XmlNode> nodes);  
}

public interface BaseBarB<T> where T : BaseThing{
  T DataFromXmlElements(IEnumerable<XmlNode> nodes, string[] fieldNames);  
}

哎呀...我写这篇文章的时候已经有其他三个答案了,你们真是太快了 :) - Ozzy

1

不太清楚你希望做什么。如果调用第一个方法,你期望发生什么?根据你的期望,你可以让父抽象类实现第一个方法,基于第二个方法已经被实现的假设:

protected internal T DataFromXmlElements(IEnumerable<XmlNode> nodes) {
    return DataFromXmlElements(nodes, null);
}

这里发生的情况是我有一个基类来处理各种XML格式和从API中读取数据。我所指的方法接受原始的XML并返回一个强类型对象。现在有一种新情况,即我在设计时不知道返回的字段,并且需要在运行时获取它们。这就是字段数组的作用......但如果可能的话,我仍然希望使用相同的基类。将较低级别的XML处理提取到另一个类中似乎可以使其更加灵活。谢谢。 - bryan

1
要么像 Colin Mackay 所说的那样使用虚拟默认实现,要么使用接口和显式实现来阻止外部调用方法。
internal interface IBaseBar1<T> where T : BaseThing
{
    T DataFromXmlElements(IEnumerable<XmlNode> nodes);
}

interface IBaseBar2<T> where T : BaseThing
{
    T DataFromXmlElements(IEnumerable<XmlNode> nodes, string[] fieldNames);
}

class FooBarMapper : IBaseBar2<FooData>
{
    FooData IBaseBar2<FooData>.DataFromXmlElements(IEnumerable<XmlNode> nodes, string[] fieldNames)
    {
        FooData o = new FooData
        {
            bar1 = bar1,
            bar2 = bar2
        };
        return o;
    }
}

1

你可以将其中一个或两个设置为虚拟的,并提供默认实现,该实现调用另一个默认参数(或根据您放置的方式而不传递值)。

但是,我怀疑您的设计可能需要更多的重新考虑,因为调用者可能会引用基类(即您的抽象类),并且不知道他们正在调用特定的派生版本,在这种情况下,调用代码应始终可以自由地调用任何它喜欢的方法。


1

不可能。

但你可以有一个单一的抽象内部基类,然后从中派生出两个抽象类(每个类都有一个抽象方法)。

最后,你可以从任意一个抽象类中派生出工作类,并实现相应的单一方法。

这“可能”行得通,但更大的问题是你是否应该这样做?我认为你可能需要重新考虑你的实现方式。


0

你不能这样做。唯一的选择是重新安排你的类。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接