LSP:里氏替换原则
* 原则上来讲,子类对象可以赋给父类对象,也可以说子类替换父类,并且出现在父类能过出现的任何地方
*
* 反过来说,父类对象时不能替换子类对象的,这种特性称为里氏替换原则
* 1.子类可以隐士的转换为父类对象
* 2.父类必须强转子类
*
* is&&as
* is :相当于判断,A is B A是不是B或者说A是不是B的子类?
* as :先判断在转换,(他比传统的强之转换相对安全,因为传统的强值转换,一旦转换失败,程序就崩溃了,)
*
* B b;定义栈上的引用变量b,此时是空引用,也就是null 存于栈,用来保存将来引用对象的地址
* b=new B:通过new关键词创建B类的对象,对象的实例保存在托管堆,CRl在建立实例对象的时候,
* 还回创建它的类型对象
* ,对象实例在堆中的内存包括,字段,类型对象指针,同步索引块,类型对象指针指向的是类型对象
*
* 类型对象在堆中的内存包括类型对象指针,索引块,静态字段,方法列表
*
* A a=new B
* ;声明一个类型为A的引用类型a,并将其实际地址指向B所指向的那个对象实例
*
* a.MethodF();
* 当调用一个方法的时候,会直接检查这个对象的类型,首先找到堆中的类型对象,查看其是否有该方法,
* 如果有,直接调用,如果没有,则通过类型对象的类型对象指针向上继续查找,直到找到该方法,
* 找到该方法之后,他会先检查该方法是否为Virtula,如果非虚直接调用,如果是需方法,既有virtual修饰的关键词
* 则会引用变量a,去找对象的实例类B,查找该方法是否重写了该虚方法,如果有,执行,没有继续向上查找,直到找到为止
*
* 由于MetthodG为需方法既会找到实例B,又由于B重写了MetthodG,所以直接输出
*
*/什么是抽象方法
*
* 抽象类:
* 在程序中使用关键字abstract
*
* 如果说正常类是一个完整类,抽象类实际上是一个不完整的类
*******************************************************************************************************
* 抽象类的特点
* 1.如果类中存在抽象方法,那么该方法不能有实现部分,该方法只能有声名
* 2.含有抽象方法的类一定是抽象类
* 3.抽象类不一定含有抽象方法
* 4.如果子类继承子类的父类为抽象类并且还有抽象方法,子类必须重写父类抽象方法并且实现
* 5.virtual和abstract不能使用private修饰符,要用public修饰符
* 6.virtual不能和abstract放在一起
* 7.抽象类不能被实例化
* 8.抽象类可以包含静态成员
*
* 抽象类的作用:
* 父类约束子类行为
**********************************************************************************************
* 接口:接口就是公共契约
* 接口的关键字:interface
* 接口和类属于同级关系,属于C#中的编程单位
* 接口也被叫纯洁的抽象类
*
* 接口特点:
* 1.不能有字段
* 2.接口内不能有修饰符
* 3.接口中不能有方法体(方法实现)
* 4.接口同样不可以被实例化
* 5.接口里面成员总是公共的
* 6.接口中可以有属性但是不能有修饰符
* 7.接口中可以有索引器/事件声明
* 8.接口中生命的方法子类实现的时候子类虽然也用override关键字,但是记住不属于重写,这里不能把override显示的声明出来
*
* 开发准则:尽量多用接口,能用接口不用抽象类,能用抽象类就不用虚方法
* 动态多态性
//里氏替换原则
class Person //父类
{
public void Say()
{
Console.WriteLine ("父类");
}
}
class Zhang:Person //子类
{
public new void Say()
{
Console.WriteLine ("张说");
}
}
class Li:Person
{
public new void Say( )
{
Console.WriteLine ("李说");
}
}
class MainClass
{
public static void Main (string[] args)
{
// Person p = new Zhang ();
// p.Say ();
//
// Person p1 = new Li ();
// Person p2 = p1;//编译通过
//
// Li l1 = p1;//编译不通过,因为父类必须强转子类
// Li l1 = (Li)p1;
// Person p=new Zhang();
// Zhang z = (Zhang)p;
// //子类和子类
// Zhang z1=new Zhang();
// Li l1 = new Li ();
//
// z1 = (Zhang)l1;//编译不通过
Person p1 = new Zhang ();
if (p1 is Zhang) {
Zhang z1=p1 as Zhang;
z1.Say();
}
else {
Console.WriteLine ("______-_-___");
}
}
//抽象类
//练习:Shap类,表示一个形状的抽象类
//该类包含一个求圆形面积的抽象方法Area()
//请从Shap的派生类,梯形,圆形,三角形,菱形实现各自的面积.
abstract class Shap{
public abstract void Area();
}
class Pai:Shap{
public int r;
public Pai(int r)//
{
this.r=r;
}
public override void Area ()
{
double m = r * r * 3.14;
Console.WriteLine ("圆形的面积为:{0}",m);
}
}
class Sanjiao:Shap
{
public int r;
public int a;
public override void Area ()
{
double m = r*a/2;
Console.WriteLine ("三角形的面积为:{0}",m);
}
}
class Tixing:Shap
{
public int r;
public int a;
public int c;
public Tixing(int r,int a ,int c)
{
this.a=a;
this.c=c;
this.r=r;
}
public override void Area ()
{
double m = (r+a)*c/2;
Console.WriteLine ("梯形的面积为:{0}",m);
}
}
class Linxing:Shap
{
public int a;
public int b;
public Linxing(int a,int b)
{
this.a=a;
this.b=b;
}
public override void Area ()
{
int m = a * b;
Console.WriteLine ("菱形的面积为:{0}",m);
}
}
class MainClass
{
public static void Main (string[] args)
{
//new Huang ().Say ();
//需要计算面积用到的参数,请自己想办法解决.
Pai p=new Pai(4);
p.Area ();
Sanjiao s = new Sanjiao ();
s.a = 6;
s.r = 3;
s.Area ();
Tixing t = new Tixing (4, 6, 6);
t.Area ();
Linxing l = new Linxing (5, 9);
l.Area ();
}
//接口
interface IInput
{
void Read();
}
interface IInputTwo
{
void Read();
}
class Test:IInput,IInputTwo
{
public string name;
//如果接口出现方法同名情况需要以下列方式实现,但是调用的时候
//要用动态多态性调用,非常规调用方式
// public void IInput.Read(){
// Console.WriteLine ("1111");
// }
//
// public void IInputTwo.Read(){
// Console.WriteLine ("2222");
// }
public void Read(){
Console.WriteLine ("1111");
}
// public void Read(){
// Console.WriteLine ("2222");
// }
public IInput T(){
Test t = new Test ();
t.name = "测试返回接口实例";
return t;
}
}
class MainClass
{
public static void Main (string[] args)
{
// new Test ().Read ();
//返回接口实例
Test t = new Test();
Console.WriteLine (t.name);
Test t1 = (Test)t.T ();
Console.WriteLine (t1.name);
// Test t = new Test ();
}