Sealed property of abstract class

2019-05-15 08:46发布

Please consider the following design:

public interface IBook
{
    string Author { get; set; }

    string Title { get; set; }
}

abstract class BaseBook : IBook
{
    private string _title;

    public virtual string Author
    {
        get
        {
            Console.WriteLine("Base book GET!");
            return _title;
        }
        set
        {
            Console.WriteLine("Base book SET!");
            _title = value;
        }
    }

    public string Title { get; set; }
}

class Book : BaseBook
{
}

class SuperBook : Book
{
    public override string Author
    {
        get
        {
            Console.WriteLine("SuperBook GET!");
            return base.Author;
        }
        set
        {
            Console.WriteLine("SuperBook SET!");
            base.Author = value;
        }
    }

    public string Title { get; set; }
}

Is there any way make the Title property of the BaseBook base class sealed to prevent the property from being overridden in derived classes (such as the Book and the SuperBook classes)?

5条回答
beautiful°
2楼-- · 2019-05-15 09:15

If you compile your program, you will receive the following warning:

prog.cs(63,19): warning CS0108: SuperBook.Title' hides inherited memberBaseBook.Title'. Use the new keyword if hiding was intended

This means that your SuperBook.Title is hiding the Title from BaseBook. Hiding is different from overriding, because the member is not virtual. What happens with hiding is this: if the compiler is treating your object as an instance of the SuperBook class, it will call the SuperBook.Title method. If, however, the compiler treats your instance as a BaseBook class, the call will be made to BaseBook.Title.

For instance:

SuperBook b1 = new SuperBook();
Console.Writeline(b1.Title); // will result in a call to SuperBook.Title
BaseBook b2 = b1;
Console.Writeline(b1.Title); // will result in a call to BaseBook.Title

If you make the property virtual, then the result is that the most derived implementation will always be called, because the compiler uses an virtual table to find which method to call.

Finally, if you want the property to be virtual so that every call gets resolved to SuperBook.Title, but don't want the user to override it on more derived classes, all you have to do mark the property sealed override.

查看更多
Animai°情兽
3楼-- · 2019-05-15 09:25

Use "sealed" keyword on your Title property.

查看更多
Explosion°爆炸
4楼-- · 2019-05-15 09:26

You won't be able to override the Title property unless it is marked virtual anyway. What you cannot prevent it from is being hidden by somebody using the new operator.

查看更多
不美不萌又怎样
5楼-- · 2019-05-15 09:27

If it's not virtual, then it cannot be overriden, it can only be hid (using thenewkeyword). Unlike Java, C# methods (and and by extension properties) are not implicitly virtual, but rather explicitly.

查看更多
女痞
6楼-- · 2019-05-15 09:28

You already cannot override BaseBook.Title. SuperBook.Title actually hides BaseBook.Title rather than overrides it. It should really have the new keyword on it if hiding was intended; in fact you'll get a compiler warning to that effect.

查看更多
登录 后发表回答