2

TL;博士

在接口中隐藏属性以便我可以更改其声明以返回原始属性的派生类型有什么问题?

我敢肯定这一定是以前问过的,但我找不到它,并为这个冗长的问题道歉。

说我有这种情况:

public interface A
{
    B TheB{get;}
}

public interface MoreSpecificA : A
{
    MoreSpecificB TheMoreSpecificB{get;}
}

public interface B{...}

public interface MoreSpecificB:B{...}

我希望 的用户MoreSpecificA能够获得 B ,即MoreSpecificB. 他们可以通过调用TheB和强制转换来做到这一点,或者他们可以调用方法TheMoreSpecificB。我也可以MoreSpecificA这样声明:

public interface MoreSpecificA : A
{
    new MoreSpecificB TheB{get;}
}

这样他们现在就可以使用相同的方法并取回MoreSpecificB.

使用new隐藏方法让我很紧张,那么为什么这是一个坏主意呢?在这里做这件事似乎很合理。

在大多数情况下,我看到的一般建议似乎是改用泛型,但这似乎有一个问题,如果我有一个MoreSpecificA并且我想在一个声明返回类型的方法中返回它,A那么我有具有MoreSpecificA扩展A,这在访问实例时会产生歧义,TheB因为MoreSpecificA它不知道您是否想要A.TheBMoreSpecificA.TheB

public interface ABase<T> where T : B
{
    T TheB{get;}
}

public interface A : ABase<B>
{        
}

public interface MoreSpecificA : ABase<MoreSpecificB>,A
{        
}

public class blah
{
    public A GetA(MoreSpecificA specificA)
    {
        return specificA; //can't do this unless MoreSpecificA extends A 
    }

    public B GetB(MoreSpecificA specificA)
    {
        return specificA.TheB; //compiler complains about ambiguity here, if MoreSpcificA extends A
    }
}

这可以通过在 MoreSpecificA 上声明一个新的 TheB 来解决(但又是新问题)。

如果 MoreSpecificA 没有扩展 A,那么blah上面类中的第一个方法现在会抱怨,因为 MoreSpcificA 无法转换为 A。

在写这篇文章时,我注意到如果我声明我的 BaseA 是这样的逆变:

public interface ABase<out T> where T : B
{
    T TheB{get;}
}

我的班级是

public class blah
{
    public ABase<B> GetA(MoreSpecificA specificA)
    {
        return specificA; 
    }

    public B GetB(MoreSpecificA specificA)
    {
        return specificA.TheB; //compiler complains about ambiguity here
    }
}

然后我得到两全其美。此解决方案的适用性是否取决于是否A添加任何内容ABase

还是我最初的计划只是将方法隐藏在派生类型中以返回原始方法的派生类型好吗?

4

1 回答 1

2

还是我最初的计划只是将方法隐藏在派生类型中以返回原始方法的派生类型好吗?

只要意思完全一样,我觉得没问题。您可以在标准库中看到类似的内容,例如IDbConnection.CreateCommand(which returns IDbCommand) 和SqlConnection.CreateCommand(which returns SqlCommand)。

在这种情况下,它对版本使用显式接口实现IDbConnection,但原理相同。

您也可以在IEnumerator<T>.CurrentvsIEnumerator.CurrentIEnumerable<T>.GetEnumerator()vs中看到它IEnumerable.GetEnumerator()

我只会在弱类型方法的实现返回调用强类型方法的结果的情况下使用它,但使用隐式转换。当他们实际上开始做不同的事情时,以后就很难推理了。

于 2012-03-20T08:11:07.223 回答