使用继承还是组合?这个问题的争论恐怕还在争论不休,微软鼓励程序员多使用继承,他们的理由是:扩展性好,因为,如果给应用添加一个功能的话,只要在基类上添加就可以了,其派生出来的子类不需要做任何修改,因为子类不需要了解父类;而对于接口来说就没这么容易了,不仅要修改接口,而且所有实现该接口的类也都要修改,这就给应用的扩展性带来了麻烦。所以微软推荐并鼓励程序员优先使用继承。
那为什么要使用接口呢?
1,可是实现同一接口的类有相同的行为(在.NET中还有属性);
2,可以限制用户操作的范围,如只给普通用户提供只读接口,那么用户就只有这些只读的操作,至于实现该接口的类还有什么其他的操作,普通用户就不得而知了,因为接口就只有这些。如:
class Program {
static void Main(string[] args) {
IBase b1 = (IBase)(new Person());
IBase b2 = (IBase)(new Employee());
Console.WriteLine(string.Format("{0}, age is {1}",b1.GetName(), b1.GetAge()));
Console.WriteLine(string.Format("{0}, age is {1}",b2.GetName(), b2.GetAge()));
//Console.WriteLine(string.Format("{0}, age is {1}", b2.GetName(), b2.Address)); //error
Console.Read();
}
}
interface IBase {
int GetAge();
string GetName();
}
class Person : IBase {
private int _age = 20;
private string _name = "mf";
public int GetAge() {
return this._age;
}
public string GetName() {
return this._name;
}
}
class Employee : IBase {
private int _age = 20;
private string _name = "mf";
private string _address = "HangZhou";
public int GetAge() {
return this._age;
}
public string GetName() {
return this._name;
}
public string Address {
get {
return this._address;
}
set {
this._address = value;
}
}
有智能感知可以看出b1,b2有相同的方法GetAge()和GetName(),而b2看不到Employee类的Address属性,尽管该属性是共有的。所以使用IBase接口访问Employee类的用户就不能修改Address属性,提高了安全性。如下图:
}图 1 b1可使用的方法列表
因此,使用继承还是接口,要根据情况而定,最好找个两全其美的方法,技能满足应用的扩展性需求又能保证应用的安全性。这就需要系统架构师的能力了。