二.面向对象
包括:对象、类、封装、继承、多态、属性、索引器、接口、泛型
1.类与对象
类:用高级程序语言实现的一个ADT描述
对象:通过类声明的常量
2.封装
封装的定义
把类的内部隐藏起来以防止外部看到内部的实现过程
抽象和封装是面向对象程序设计的相关特性。抽象允许相关信息可视化,封装则使开发者实现所需级别的抽象。
封装的实现
C# 封装根据具体的需要,设置使用者的访问权限,并通过 访问修饰符 来实现。
一个 访问修饰符 定义了一个类成员的范围和可见性。
- 对类中数据(Data)和操作(operation)的限制修饰符:
- private:对象本身在对象内部可以访问(默认);
- protected:只有该类对象及其子类对象可以访问
- public:所有对象(类的内部外部)都可以访问;
- internal:同一个程序集(项目)的内部访问,相当于public;
- 对类的限制修饰符:
- public:都可以使用
- internal:在同一程序集(项目) 内部使用(默认)
类成员封装类型未定义时,默认为private
封装的表示
- 类图
例:根据下列类图实现Animal类型
public class Animal
{
public int Age;
public double Weight;
public void Eat()
{
Console.WriteLine("Animal Eat")
}
public void Sleep
{
Console.WriteLine("Animal Sleep")
}
}
3.继承
3.1 继承的概念
子类拥有父类的某些Data和Operation的过程
3.2 继承的实现
- public class Child:Paren{…}
- Child:子类(派生类),Parent:父类(基类)
- 在类的声明中,利用“:”表示继承
- C#只支持单继承,不允许多继承
- public sealed class Name
- 利用sealed关键字可防止所声明的类被继承
- 父类 public protected private internal
- 子类 public protected 无法继承 internal
3.3 子类怎样访问父类成员
利用base关键字
- 例:子类访问父类且父类构造函数不带参数
- 例 子类访问父类且父类构造函数带参数
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 封装
{
class Program
{
static void Main(string[] args)
{
Class2 class2=new Class2();
Console.WriteLine(class2.data3);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 封装
{
public class Class1
{
private int data1;//只能被类的内部访问
protected int data2;//能被子类访问和继承
public int data3;//能被子类访问和继承
//构造函数具有形参
public Class1(int dt1, int dt2, int dt3)
{
data1 = dt1;
data2 = dt2;
data3 = dt3;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 封装
{
public class Class2:Class1
{
//继承时候因父类构造函数具有形参,需提供base(形参)
//或者 public class Class2(int x,int y,int z):base(x,y,z)
public Class2():base(0,2,3)
{ ;
}
}
}
3.4 怎样表示
- 通过类图来表示
例:根据类图实现程序代码,注意类之间的继承关系
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Animal2
{
public class Animal
{
public int Age;
public float Weight();
public void Eat()
{
Console.WriteLine("Animal Eat");
}
public void Sleep()
{
Console.WriteLine("Animal Sleep");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Animal2
{
public class Dog:Animal
{
public void Run()
{
Console.WriteLine("Dog Run");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Animal2
{
public class Bird:Animal
{
public void Fly()
{
Console.WriteLine("Bird Fly");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Animal2
{
public class Fish:Animal
{
public void Swim()
{
Console.WriteLine("Fish swim");
}
}
}
3.5实例化
为对象分配存储空间的过程
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Animal2
{
class Program
{
static void Main(string[] args)
{
Animal al = new Animal(); // 实例化Animal
al.Eat();
al.Sleep();
Dog dg = new Dog(); // 实例化Dog
dg.Age = 2;
dg.Weight = 4.5;
dg.Sleep();//继承下来的
dg.Eat();//继承下来的
dg.Run();
}
}
}
- 子类与父类有重名方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Animal2
{
class Program
{
static void Main(string[]args)
{
Animal al = new Animal(); // 子类可以实例化父类
al.Eat();//重名方法存在问题
al.Sleep();
Dog dg = new Dog(); // 强制类型转换或Dog dg =(Dog)al;
dg.Age = 2;
dg.Weight = 4.5;
dg.Sleep();
dg.Eat();
dg.Run();
}
}
}
4.多态
4.1 什么是多态
相同的操作,对于不同的对象,可以有不同的解释,产生不同的执行结果
4.2 多态的分类
- 运行时多态:在运行时决定执行哪个类的哪个方法(override覆写)
处理子类父类运行方法时出现重名的情况,运行哪个方法 - 编译时多态:在编译时决定执行类的哪个方法(overload重载)
同一个类的内部会产生编译时多态,方法的重载,运算符的重载
4.3 多态的实现
- 运行时多态:
- 在父类中定义并实现虚方法(virtural)
- 在子类中覆写(override)该虚方法
- 虚方法必须有方法体,和abstract进行区分
- 覆写虚方法,要求方法名,形参,返回值类型必须相同
例 :通过类图实现运行时多态
- 编译时多态
- 类中定义的方法或操作符可能有不同的版本
- 操作符的重载:operator 关键字
-
- public static 类型(返回值类型) operator 运算符(形参类型){…}
- 方法的重载:必须有相同的方法名、必须有不同的参数列表、可以有相同的返回值类型
例:通过类图实现编译时多态的代码
4.4抽象方法与抽象类
- 抽象方法:可以看成没有实现体的虚方法(abstract),即只有方法的声明,需要在子类中覆写(override)该方法
- 抽象类:含有抽象方法的类。抽象类不可以直接实例化对象
- 例:通过类图实现抽象类及其实现的代码
类图中的方法名称斜体表示此为虚方法(abstract)
因为含有抽象方法应该注明为抽象类
在子类中覆写抽象方法
- 例:饲养系统
方案一:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Animal2
{
class Program
{
static void Main(string[] args)
{
Raiser rar = new Raiser();
rar.RaiseBird();
rar.RaiseDog();
rar.RaiseFish();
}
}
}
using System;
using
System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Animal2
{
public class Dog
{
public void Run()
{
Console.WriteLine("Dog
Run");
}
public void Eat()
{
Console.WriteLine("Dog
Eat");
}
public void Sleep()
{
Console.WriteLine("Dog
Sleep");
}
}
}
using System;
using
System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Animal2
{
public class Bird
{
public void Fly()
{
Console.WriteLine("Bird
Fly");
}
public void Eat()
{
Console.WriteLine("Dog
Eat");
}
public void Sleep()
{
Console.WriteLine("Dog
Sleep");
}
}
}
using System;
using
System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Animal2
{
public class Fish
{
public void Swim()
{
Console.WriteLine("Fish
swim");
}
public void Eat()
{
Console.WriteLine("Dog
Eat");
}
public void Sleep()
{
Console.WriteLine("Dog
Sleep");
}
}
}
using System;
using
System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Animal2
{
class Raiser
{
public void
RaiseDog()
{
Dog dog = new Dog();
dog.Eat();
dog.Sleep();
}
public void
RaiseFish()
{
Fish fish=new Fish();
fish.Eat();
fish.Sleep();
}
public void
RaiseBird()
{
Bird bird = new Bird();
bird.Eat();
bird.Sleep();
}
}
}
- 方案2:
namespace Animal2
{
class Program
{
static void Main(string[] args)
{
Raiser rar = new Raiser();
rar.Raise(AnimalType.Dog);
rar.Raise(AnimalType.Fish);
rar.Raise(AnimalType.Bird);
}
}
}
namespace Animal2
{
public enum AnimalType { Dog,Bird,Fish };
public class Raiser
{
public void Raise(AnimalType alt)
{
switch (alt)
{
case AnimalType.Bird:
Bird bird = new Bird();
bird.Sleep();
bird.Eat();
break;
case AnimalType.Dog:
Dog dog=new Dog();
dog.Sleep();
dog.Eat();
break;
case AnimalType.Fish:
Fish fish=new Fish();
fish.Sleep();
fish.Eat();
break;
}
}
}
}
- 方案三