访问修饰符
- public:公开的,所有对象都可以访问
- private:私有的,类的内部可以访问
- protected:保护的,类的内部和子类可以访问(类外实例出来的本类对象无法访问)
- internal:同一命名空间可访问
继承:
public class A
{
private string name;
public void Info()
{
console.WriteLine("AA");
}
public void News()
{
console.writeLine("CC");
}
public void Main()
{
Info();//AA
}
}
//类B继承类A,A是基类,B是派生类
public class B:A
{
private string sex;
public void Info()
{
console.WriteLine("BB");
}
public void Main()
{
Info();//BB
base.Info();//AA
}
}
class Program
{
static void Main(string[] args)
{
//B实例化时,会先给本身类的字段(sex)声明空间,再给父类的字段(name)声明空间。
B b=new B();
b.Info();//BB
b.News();//CC
}
}
- 子类实例化时,会先给子类的字段声明空间,再给父类字段声明空间。
- 子类里可以调用父类 公开或保护 的方法和成员变量
- 子类实例化后,可调用父类公开的 方法/成员变量,不可调用保护的成员变量或方法。
- 子类中或子类实例化中,若调用与父类同名的方法,会优先调用子类的方法。
- 子类中可以用 base. 来调用父类同名方法/成员变量
多重继承指的是一个类别可以同时从多于一个父类继承行为与特征的功能。与单一继承相对,单一继承指一个类别只可以继承自一个父类。
C# 不支持多重继承。但是,可以使用接口来实现多重继承
多态性
多态是同一个行为具有多个不同表现形式或形态的能力。
多态性意味着有多重形式。在面向对象编程范式中,多态性往往表现为"一个接口,多个功能"。
多态性可以是静态的或动态的。在静态多态性中,函数的响应是在编译时发生的。在动态多态性中,函数的响应是在运行时发生的。
静态多态性(早期绑定):函数重载/运算符重载。
函数重载:在同一范围内对相同函数名有多个定义,可以是参数类型或参数个数的不同,但不许只有返回值类型不同。
动态多态性:抽象类/虚方法
抽象类
关键字 abstract 来创建抽象类,一个接口提供多个功能。当一个派生类继承自该抽象类时,实现即完成。抽象类包含抽象方法,抽象方法可被派生类实现。
- 不能创建一个抽象类的实例。
- 不能在一个抽象类外部声明一个抽象方法(抽象方法必须写在抽象类内)
- 通过在类定义前面放置关键字 sealed,可以将类声明为密封类。当一个类被声明为 sealed 时,它不能被继承。抽象类不能被声明为 sealed。
abstract public class A
{
abstract public string GetInfo();//定义抽象方法
}
class B:A
{
public override string GetInfo()//重写
{...
}
}
class C:A
{
public override string GetInfo()//重写
{...
}
}
注意:
- 抽象方法没有方法体(无法调用),且继承了抽象类的子类必须重写(override)所有抽象方法
- 抽象类不能创造实例
- 抽象方法必须写在抽象类里,抽象类中可以包含非抽象方法
虚方法 virtual
virtual关键字来创虚方法,虚方法可以被子类调用
public class A
{ //定义虚方法
public virtual void Info()
{
console.WriteLine("我是:");
}
}
public class B:A
{
//重写
public override void Info()
{
base.Info();
console.WriteLine("xiaom");
}
}
public class C:A
{
//重写
public override void Info()
{
base.Info();
console.WriteLine("xiaoz");
}
}
public class D:A
{
}
class Test
{
static void Main(string[] args)
{
B b=new B();
C c=new C();
D d=new D();
b.Info();//我是:xiaom
c.Info();//我是:xiaow
d.Info();//我是:
}
}
注:父类中定义虚方法,子类中既可以重写该方法。虚方法有方法体,子类中base.可调用。
虚方法和抽象方法必须是公开的
接口 interface关键字
//定义一个接口
interface MyInterface
{
void FirstInterface();//接口方法
}
//类A继承接口
class A:MyInterface
{
public void FirstInterface()
{...
}
}
//类B继承接口
class B:MyInterface
{
public void FirstInterface()
{...
}
}
接口注意的几点:
- 接口方法不能用public abstract等修饰。接口内不能有字段变量,构造函数。
- 接口内可以定义属性(有get和set的方法)。如string color { get ; set ; }这种。
- 必须实现接口的所有方法和属性。
- 实现接口时,必须和接口的格式一致。
多重继承
//定义一个接口
interface MyInterface1
{
void FirstInterface1();//接口方法
}
//继承接口1
interface MyInterface2:MyInterface1
{
void FirstInterface2();//接口方法
}
//类A继承接口
class A:MyInterface2
{
public void FirstInterface1()//实现方法
{...
}
public void FirstInterface2()//实现方法
{...
}
}
//类B继承接口
class B:MyInterface2
{
public void FirstInterface1()
{...
}
public void FirstInterface2()
{...
}
}
接口的定义是指定一组函数成员而不实现成员的引用类型,其它类型和接口可以继承接口。接口主要有以下特点:
- (1)通过接口可以实现多重继承,C# 接口的成员不能有 public、protected、internal、private 等修饰符。原因很简单,接口里面的方法和属性都需要由外面接口实现去实现方法体,那么其修饰符必然是 public。C# 接口中的成员默认是 public 的。
- (2)接口成员不能有 new、static、abstract、override、virtual 修饰符。有一点要注意,当一个接口实现一个接口,这2个接口中有相同的方法时,可用 new 关键字隐藏父接口中的方法。
- (3)接口中只包含成员的签名,接口没有构造函数,所有不能直接使用 new 对接口进行实例化。接口中只能包含方法、属性、事件和索引的组合。接口一旦被实现,实现类必须实现接口中的所有成员,除非实现类本身是抽象类。
- (4)C# 是单继承,接口是解决 C# 里面类可以同时继承多个基类的问题。
接口和抽象类的区别
接口用于规范,抽象类用于共性。抽象类是类,所以只能被单继承,但是接口却可以一次实现多个。
接口中只能声明方法,属性,事件,索引器。而抽象类中可以有方法的实现,也可以定义非静态的类变量。
抽象类可以提供某些方法的部分实现,接口不可以。抽象类的实例是它的子类给出的。接口的实例是实现接口的类给出的。
在抽象类中加入一个方法,那么它的子类就同时有了这个方法。而在接口中加入新的方法,那么实现它的类就要重新编写(这就是为什么说接口是一个类的规范了)。
接口成员被定义为公共的,但抽象类的成员也可以是私有的、受保护的、内部的或受保护的内部成员(其中受保护的内部成员只能在应用程序的代码或派生类中访问)。
此外接口不能包含字段、构造函数、析构函数、静态成员或常量。