Interface inheritance: is extending properties pos

2020-05-21 12:23发布

I want to do this:

interface IBase
{
    string Property1 { get; }
}

interface IInherited : IBase
{
    string Property1 { get; set; }
}

So that IInherited would have the inherited property Property1 with added functionality to allow set.

Is that possible? What's the syntax?

EDIT: please notice I put the word "inherited" in bold face. I am asking specifically about inheriting the property, not hiding it behind a new one.

6条回答
狗以群分
2楼-- · 2020-05-21 12:46

If the fact that the only way to do this is by using the new keyword bothers you, then in my opinion you're thinking about interfaces wrong.

Sure, you could say that IInherited "inherits from" IBase; but what does that really mean? These are interfaces; they establish code contracts. By hiding the IBase.Property1 property with new string Property1 { get; set; }, you are not shadowing any functionality. Thus the traditional reason that a lot of developers consider hiding to be a "bad" thing -- that it violates polymorphism -- is irrelevant in this case.

Ask yourself: what really matters when it comes to interfaces? They provide a guarantee of responding to certain method calls, right?

So, given the following two interfaces:

interface IBase
{
    string Property1 { get; }
}

interface IInherited : IBase
{
    new string Property1 { set; }
}
  1. If an object implements IBase, you can read its Property1 property.
  2. If an object implements IInherited, you can read its Property1 property (just as with an IBase implementation), and you can also write to it.

Again, there's really nothing problematic here.

查看更多
\"骚年 ilove
3楼-- · 2020-05-21 12:50

You can either mark the property with the "new" keyword, or you can skip the inheritance:

public interface IBase
{
    string Property1 { get; }
}

public interface IInherited : IBase
{
    new string Property1 { get; set; }
}

Or:

public interface IBase
{
    string Property1 { get; }
}

public interface IInherited
{
    string Property1 { get; set; }
}

Either way, this should work:

public class SomeClass : IInherited, IBase
{
    public string Property1
    {
        get
        {
            // ...
        }
        set
        {
            // ...
        }
    }
}

You may want to think hard before you make an inheritance chain for your interfaces, though. Who is going to see which interface? Would you need to cast to IInherited when passed an IBase? If so, can you be guaranteed that you can do that cast (if you allow user created classes, then the answer is no)? This kind of inheritance can really hurt (re)usability if you're not careful.

查看更多
疯言疯语
4楼-- · 2020-05-21 12:52

Your code should work anyway... it just creates a complier warning because of hiding Property1. To clear this warning mark Property1 in IInherited with the new prefix

查看更多
我想做一个坏孩纸
5楼-- · 2020-05-21 12:55

Hiding a member is violating the Liskov Substitution Principle and pretty much just shouldn't be done, ever. By hiding this member you are introducing a very difficult to locate bug since 2 different outcomes will occur depending whether you cast the object as IBase1 or cast it to IBase.

http://en.wikipedia.org/wiki/Liskov_substitution_principle

查看更多
Juvenile、少年°
6楼-- · 2020-05-21 12:59

Unfortunately not - properties cannot be extended as such. However, you can just hide the property by using new:

interface IInherited : IBase
{
    // The new is actually unnecessary (you get warnings though), hiding is automatic
    new string Property1 { get; set; }
}

Or, you can make your own getter and setter methods which can be overriden (good 'ol Java style):

interface IBase
{
    string GetProperty1();
}
interface IInherited : IBase
{
    void SetProperty1(string str);
}

Properties are actually converted to getter and setter methods by the compiler.

查看更多
劳资没心,怎么记你
7楼-- · 2020-05-21 13:10

Not explicitly, no. You have two options:

public interface IBase
{
    string Property1 { get; }
}

public interface IInherited : IBase
{
    void SetProperty1(string value);
}

Or you can just kill the compiler warning with the new keyword:

public interface IBase
{
    string Property1 { get; }
}

public interface IInherited : IBase
{
    new string Property1 { get; set; }
}

Unless you implement IInherited.Property1 explicitly, IBase will bind to your settable implementation automatically.

查看更多
登录 后发表回答