面向对象技术
- 包括:对象、类、封装、继承、多态、属性、索引器、接口(interface)、泛型(参数类型)
类与对象
- 类:用高级程序语言实现的一个ADT描述
- 对象:通过类声明的变量
封装
- 封装的定义:把类的内部隐藏起来以防止外部看到内部的实现过程
- 封装的实现:通过限制修饰符
private,protected,public,internal
来实现
对类中的数据(Data)和操作(Operation)的限制修饰符: private
:只允许类的内部访问(默认)protected
:只允许类的内部和子类访问public
:类的内部与外部都可以访问internal
:在同一命名空间内部访问,相当于public
对类的限制修饰符public
:都可以使用
注:在不同的项目中,通过添加引用internal
:在同一程序集Assembly
(项目)内部使用
注:namespace
不同时,在前面加上using xxxx
- 封装的表示:类图
(Class Diagram)
using System;
using System.Collections.Generic;
using System.Text;
namespace Internal.demo
{
public class Animal
{
public int Age;
public double Weight;
public void Eat()
{
Console.WriteLine("Animal Eat.");
}
public void Sleep()
{
Console.WriteLine("Animal Sleep.");
}
}
}
继承
- 继承的定义:子类拥有父类某些
Data
和Operation
的过程
public class Child : Parent{...}
Child:子类(派生类),Parent:父类(基类)
在类的声明中,利用":"表示继承
- C#只支持单继承
- 利用
sealed
关键字可防止所声明的类被继承
public sealed class Name
//利用sealed关键字可防止所声明的类被继承
- 继承关系
父类 public 子类 public
protected protected
private 无法继承
internal internal
- 子类访问父类成员:利用
base关键字
子类访问父类且父类构造函数不带参数
:
//父类
using System;
using System.Collections.Generic;
using System.Text;
namespace Inherit.demo
{
public class Parent
{
private int data1;//只能被类的内部访问
protected int data2;//能被子类访问和继承
public int data3;//能倍子类访问和继承
}
}
//子类
using System;
using System.Collections.Generic;
using System.Text;
namespace Inherit.demo
{
public class Child : Parent
{
public Child()
{
base.data2 = 2;
base.data3 = 3;
}
}
}
//隐藏了base = new parent();
using System;
namespace Inherit.demo
{
class Program
{
static void Main(string[] args)
{
Child cld = new Child();
Console.WriteLine(cld.data3);
}
}
}
//只能访问public的数据(data3)
子类访问父类且父类构造参数带参数
:
base = new parent()
//而parent的构造函数带参数
//子类进行实例化时需要传参进去
//父类
using System;
using System.Collections.Generic;
using System.Text;
namespace Inherit.demo
{
public class Parent
{
private int data1;//只能被类的内部访问
protected int data2;//能被子类访问和继承
public int data3;//能倍子类访问和继承
public Parent(int dt1, int dt2, int dt3)
{
data1 = dt1;
data2 = dt2;
data3 = dt3;
}
}
}
//子类
using System;
using System.Collections.Generic;
using System.Text;
namespace Inherit.demo
{
public class Child : Parent
{
public Child():base(0,2,3)
{
}
}
}
using System;
namespace Inherit.demo
{
class Program
{
static void Main(string[] args)
{
Child cld = new Child();
Console.WriteLine(cld.data3);
}
}
}
//3
- 继承的表示:通过类图来表示
- 子类可以实例化父类
- 父类不可以实例化子类
Animal al = new Dog();正确的
Dog dg = new Animal();错误的
//父类
using System;
using System.Collections.Generic;
using System.Text;
namespace Inherit.demo1
{
public class Animal
{
public int Age;
public double Weight;
public void Eat()
{
Console.WriteLine("Animal Eat");
}
public void Sleep()
{
Console.WriteLine("Animal Sleep");
}
}
}
//子类
using System;
using System.Collections.Generic;
using System.Text;
namespace Inherit.demo1
{
public class Dog : Animal
{
public void Run()
{
Console.WriteLine("Dog Run");
}
}
}
using System;
namespace Inherit.demo1
{
class Program
{
static void Main(string[] args)
{
Animal al = new Animal();
al.Age = 20;
Console.WriteLine("Animal Age:{0}", al.Age);
Dog dog = new Dog();
dog.Eat();//继承下来的
dog.Sleep();//继承下来的
dog.Run();
}
}
}
//
Animal Age:20
Animal Eat
Animal Sleep
Dog Run
- 子类与父类有重名方法:
//子类
using System;
using System.Collections.Generic;
using System.Text;
namespace Inherit.demo1
{
public class Dog : Animal
{
public void Eat()
{
Console.WriteLine("Dog Eat");
}
public void Sleep()
{
Console.WriteLine("Dog Sleep");
}
public void Run()
{
Console.WriteLine("Dog Run");
}
}
}
using System;
namespace Inherit.demo1
{
class Program
{
static void Main(string[] args)
{
Animal al = new Dog();
al.Eat();
al.Sleep();
Dog dog = al as Dog;//强制类型转换
dog.Eat();//继承下来的
dog.Sleep();//继承下来的
dog.Run();
}
}
}
//
Animal Eat
Animal Sleep
Dog Eat
Dog Sleep
Dog Run
- 强制类型转换
Dog dog = al2 as Dog;//转化不过去会赋一个null
Dog dog = (Dog)al2;
多态
- 多态的定义:相同的操作
Operation
,对于不同的对象,可以有不同的解释,产生不同的执行结果
多态的分类: - 运行时多态:在运行时决定执行哪个类的哪个方法
override覆写
- 编译时多态:在编译时决定执行类中的哪个方法
overload重载
多态的实现:
运行时多态:
在父类中定义并实现虚方法(virtual)
在子类中覆写(override)该虚方法
虚方法必须有方法体
覆写虚方法,要求方法名,形参,返回值类型必须相同
//父类
using System;
using System.Collections.Generic;
using System.Text;
namespace Inherit.demo1
{
public class Animal
{
public int Age;
public double Weight;
public virtual void Eat()
{
Console.WriteLine("Animal Eat");
}
public virtual void Sleep()
{
Console.WriteLine("Animal Sleep");
}
}
}
//子类
using System;
using System.Collections.Generic;
using System.Text;
namespace Inherit.demo1
{
public class Dog : Animal
{
public override void Eat()
{
Console.WriteLine("Dog Eat");
}
public override void Sleep()
{
Console.WriteLine("Dog Sleep");
}
public void Run()
{
Console.WriteLine("Dog Run");
}
}
}
using System;
using System.Collections.Generic;
namespace Inherit.demo1
{
public class Solution
{
class Program
{
static void Main(string[] args)
{
Animal al = new Dog();
al.Eat();
al.Sleep();
}
}
}
}
//
Dog Eat
Dog Sleep
编译时多态
类中定义的方法或操作符可能有不同的版本
操作符重载:operator关键字
public static 类型 operator 运算符(形参列表){…}
方法重载:必须有相同的方法名、必须有不同的参数列表、可以有相同的返回值类型
- 运算符重载:
class Program
{
public class Complex
{
public int A;
public int B;
public Complex(int a, int b)
{
this.A = a;//this表示在内存中的Complex对象
this.B = b;
}
public static Complex operator +(Complex c1, Complex c2)
{
return new Complex(c1.A + c2.A, c1.B + c2.B);
}
public override string ToString()
{
return string.Format("{0}+{1}i", A, B);
}
}
- 方法重载
using System;
using System.Collections.Generic;
using System.Text;
namespace Overload
{
public class Math
{
public int Add(int x, int y)
{
return x + y;
}
public double Add(double x, double y)
{
return x + y;
}
public Complex Add(Complex x, Complex y)
{
return x + y;
}
}
}
using System;
namespace Overload
{
class Program
{
static void Main(string[] args)
{
Complex C1 = new Complex(1, 2);
Complex C2 = new Complex(3, 4);
Complex C3 = C1 + C2;
Console.WriteLine(C1);
Console.WriteLine(C2);
Console.WriteLine(C3);
Math mth = new Math();
Complex C4 = mth.Add(C2,C3);//在编译时根据参数列表决定执行类中方法
Console.WriteLine(C4);
}
}
}
//
1+2i
3+4i
4+6i
7+10i
抽象方法与抽象类
- **抽象方法的定义:**可以看成没有实现体的虚方法
abstract
,即只有方法的声明,需要在子类中覆写override
该方法 - **抽象类的定义:**含有抽象方法的类,抽象类不可以直接实例化对象
斜体的表示抽象类和抽象方法
//父类
public abstract class Animal
{
public int Age;
public double Weight;
public abstract void Eat();
public abstract void Sleep();
public override string ToString()
{
return string.Format("Animal Age:{0},Weight:{1}", Age, Weight);
}
}
//子类
public class Dog : Animal
{
public override void Eat()
{
Console.WriteLine("Dog Eat");
}
public override void Sleep()
{
Console.WriteLine("Dog Sleep");
}
public void Run()
{
Console.WriteLine("Dog Run");
}
}
static void Main(string[] args)
{
Animal al = new Dog();
al.Age = 20;
al.Weight = 102.2;
al.Eat();
al.Sleep();
((Dog)al).Run();//强制类型转换
Console.WriteLine(al);
}
//
Dog Eat
Dog Sleep
Dog Run
Animal Age:20,Weight:102.2
//
Animal al = new Animal();(错误)
抽象类不可以直接实例化对象,系统会抛出异常
ex1
- 开闭原则:对扩展开放,对修改封闭
方案一:不满足开闭原则 - 在扩展时要添加类
- 在
Raiser
中要添加类方法
//Raiser
using System;
using System.Collections.Generic;
using System.Text;
namespace RaiseSystem.demo
{
public class Raiser
{
public void RaiseBird()
{
Bird bird = new Bird();
bird.Eat();
bird.Sleep();
}
public void RaiseDog()
{
Dog dog = new Dog();
dog.Eat();
dog.Sleep();
}
public void RaiseFish()
{
Fish fish = new Fish();
fish.Eat();
fish.Sleep();
}
}
}
//Dog
using System;
using System.Collections.Generic;
using System.Text;
namespace RaiseSystem.demo
{
public class Dog
{
public void Eat()
{
Console.WriteLine("Dog Eat");
}
public void Sleep()
{
Console.WriteLine("Dog Sleep");
}
public void Run()
{
Console.WriteLine("Dog Run");
}
}
}
//Bird
using System;
using System.Collections.Generic;
using System.Text;
namespace RaiseSystem.demo
{
public class Bird
{
public void Eat()
{
Console.WriteLine("Bird Eat");
}
public void Sleep()
{
Console.WriteLine("Bird Sleep");
}
public void Fly()
{
Console.WriteLine("Bird Fly");
}
}
}
//Fish
using System;
using System.Collections.Generic;
using System.Text;
namespace RaiseSystem.demo
{
public class Fish
{
public void Eat()
{
Console.WriteLine("Fish Eat");
}
public void Sleep()
{
Console.WriteLine("Fish Sleep");
}
public void Swim()
{
Console.WriteLine("Fish Swim");
}
}
}
//客户端
using System;
namespace RaiseSystem.demo
{
class Program
{
static void Main(string[] args)
{
Raiser raiser = new Raiser();
raiser.RaiseDog();
raiser.RaiseBird();
raiser.RaiseFish();
}
}
}
//
Dog Eat
Dog Sleep
Bird Eat
Bird Sleep
Fish Eat
Fish Sleep
方案二:利用枚举类型enum
(不满足封闭原则)
//改变Raiser 其他不变
using System;
using System.Collections.Generic;
using System.Text;
namespace RaiseSystem.demo
{
public enum AnimalType { Bird, Fish, Dog, Pig };
public class Raiser
{
public void Raise(AnimalType animalType)
{
switch (animalType)
{
case AnimalType.Dog:
Dog dog = new Dog();
dog.Eat();
dog.Sleep();
break;
case AnimalType.Bird:
Bird bird = new Bird();
bird.Eat();
bird.Sleep();
break;
case AnimalType.Fish:
Fish fish = new Fish();
fish.Eat();
fish.Sleep();
break;
}
}
}
}
//客户端
using System;
namespace RaiseSystem.demo
{
class Program
{
static void Main(string[] args)
{
Raiser raiser = new Raiser();
raiser.Raise(AnimalType.Dog);
raiser.Raise(AnimalType.Fish);
raiser.Raise(AnimalType.Bird);
}
}
}
//
Dog Eat
Dog Sleep
Fish Eat
Fish Sleep
Bird Eat
Bird Sleep
方案三:利用继承和多态
- 依赖于抽象,不依赖于具体
using System;
using System.Collections.Generic;
using System.Text;
namespace RaiserSystem.demo.Solution3
{
public class Raiser
{
public void Raise(Animal al)
{
if (al == null)
throw new ArgumentNullException();
al.Eat();
al.Sleep();
}
}
}
//剩下的根据类图上面已经写过
using System;
namespace RaiserSystem.demo.Solution3
{
class Program
{
static void Main(string[] args)
{
Raiser raiser = new Raiser();
raiser.Raise(new Dog());
raiser.Raise(new Bird());
raiser.Raise(new Fish());
}
}
}
//在进行扩展开发时只需要添加一个类即可
程序七大原则
- 单一职责(封装)
- 开闭原则
- 里氏替代原则
- 依赖倒转(依赖于抽象,不依赖于具体)
- 接口隔离
- 迪米特法则
- 合成复用原则