OOP(里氏替换原则 ,抽象类,接口)

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 ();

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,785评论 18 399
  • 1. [C#语言基础]请简述拆箱和装箱。 答: 装箱操作: 值类型隐式转换为object类型或由此值类型实现的任何...
    胤醚貔貅阅读 4,903评论 1 29
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,026评论 19 139
  • 目录本次给大家介绍的是我收集以及自己个人保存一些.NET面试题第二篇简介1.接口2.您在什么情况下会用到虚方法或抽...
    寒剑飘零阅读 1,995评论 0 10
  • 前两天参加一个峰会,某位企业家说,我们一定要去美国纽约时代广场,占据最大的广告屏幕,让中国货和五星红旗飘扬在美利坚...
    韦青青青阅读 534评论 0 0