1

可能的重复:
接口与抽象类(一般 OO)

MSDN文章之一中提到了以下行

接口不能在以后的版本中指定新成员,而抽象类可以根据需要添加成员以支持附加功能。

我从这里挑选了这句话。您可以阅读第 3 段中的相同句子。

我有一个困惑,提前抱歉,以防我遗漏了什么。

一旦声明了抽象类或接口,然后任何派生类都继承了这些方法,在任何一种情况下,所有方法都应该被覆盖。否则会出现编译错误。

你的评论?

4

4 回答 4

4

一旦声明了抽象类或接口,然后任何派生类都继承了这些方法,在任何一种情况下,所有方法都应该被覆盖。否则会出现编译错误。

不,对于抽象类,只需要重写抽象方法。您可以添加没有错误的非抽象方法。

例如,版本 1:

public abstract class FooBase
{
    public abstract void Bar();    
}

public class FooImpl : FooBase
{
    public override void Bar() {}
}

现在在版本 2中引入一个新的非抽象方法:FooBase

public abstract class FooBase
{
    public abstract void Bar();   

    public void NewMethod() {}
}

……没有问题。

请注意,对于公司内部代码,将同时重建所有将使用 API 的代码,这通常根本不是问题,无论是接口还是抽象类。如果您想向接口添加方法,您可以这样做,因为您可以同时升级所有实现。

确实,当您无法控制整个代码库时,您需要小心。

于 2012-11-28T17:52:18.193 回答
1

实现接口的类必须实现接口中定义的所有方法和属性。

从抽象类继承时,您必须实现/覆盖所有抽象成员,但任何非抽象成员都将被继承,就像从具体类继承时一样。

于 2012-11-28T17:54:43.570 回答
0

从接口继承时,必须实现该接口的所有成员。但是您可以根据需要扩展界面。您还可以继承多个接口。有效示例:

public interface IPerson
{
    string FullName { get; set; }
    string SSN { get; set; }
}

public interface IPersonDBContext
{
    void Save(IPerson person);
}

public class PersonData : IPerson, IPersonDBContext
{
    // Implements IPerson FullName
    public string FullName { get; set; }

    // Implements IPerson SSN
    public string SSN { get; set; }

    // Implements IPersonDBContext Save()
    public void Save(IPerson person)
    {
        // Code to save the IPerson instance to the DB...
    }

    // Added method, not included in any interface...
    public void Validate(IPerson person)
    {
        // Code to validate the IPerson instance...
    }
}

现在,对于抽象类,您可以包含可以继承的具体方法,也可以指定一些必须重写的方法。但是,请注意,您不能拥有多个基类(并且抽象类仍然是一个类......)所以您不能像接口那样混合两个抽象类。例子:

public abstract class Person
{
    public string FullName { get; set; }
    public string SSN { get; set; }

    public abstract void Save();
}

public class PersonData : Person
{
    // Implements Abstract Person Save() Method
    public override void Save()
    {
        // Save logic here...
    }

    // Non-inherited member...
    public void Validate()
    {
        // Access properties of the base class (Abstract Person)
        this.FullName.ToString();
        this.SSN.ToString();
    }
}

最后,也是最强大的,您可以将单个抽象基类与任意数量的接口混合在一起......所以,如果我保留示例 2 中的抽象类 Person 和示例 1 中的接口 IPersonDBContext,我可以这样做:

public class PersonData : Person, IPersonDBContext
{
    // Implements Abstract Person Save() Method
    public override void Validate()
    {
        // Access properties of the base class (Abstract Person)
        this.FullName.ToString();
        this.SSN.ToString();
    }

    // Inplmenets IPersonDBContext Save()
    public void Save(Person person)
    {
        // Save logic here...
    }

    // Non-inhereted method
    public void Clone(Person person)
    {
        // Logic to make a member-wise clone.
    }
}

希望有帮助...

于 2012-11-28T18:17:58.693 回答
0

实现一个接口会迫使你重写它的方法——然而继承一个类会给你一个选择。只有抽象方法需要被覆盖。MSDN 摘录指出,当所有实现者都需要实现添加的方法时,严格接口契约的价格可能会在以后证明是昂贵的。使用带有虚拟方法的父类可以让您稍后决定是否需要专门化。

于 2012-11-28T18:08:21.597 回答