1.继承
面向对象的三大特征: 封装性 继承性 多态性
一.继承:类与类的关系
为什么会用继承:减少代码重复 优化 空间内存 实现多态
class 基类 { //基类成员 } class 子类:基类 { //子类成员 }
判断继承关系 用进行进行判断--》子类对象 is 父类成员
例如 诺基亚手机 诺基亚280 诺基亚板砖007
继承特征 :1.单根性 一个只能继承自一个类 不可能继承俩个类
2.传递性 爷爷 父亲 孙子
3.派生于object根类(c#范围) c#里面的所有成员都来源于object 用于实现多态
注意: 1.继承中构造函数的问题 其实就是执行顺序
2.可以手动添加一个无参构造方法
3.访问修饰符
继承练习:
写一个student类 姓名 性别 年龄 hello方法与teacher类 姓名 性别 年龄 工资 hello方法 通过构造方法为成员赋初值 说hello
class student { private string _name; private string _age; private string _gender;//三个字段填充类的信息 public Student (string name ,int age ,char gender)//方法给三个字段赋值 –->4 {
_name=name; _age=age; _gender=gender; } public string Name { get{return _name;} } public int Age { get {return _age;} } public char Gender { get {return _gender} } //三个属性限制访问级别 为了数据安全 }
class Teather : Student { private int _score; public Teacher(string name , int age ,char gender , int score): base (name ,age ,gender)—->3 -->5 { _score =score; } public void Hello() -->7 { Console.WriteLine("大家好,我叫{0},今年{1}岁了,我是{2}生,我这次考了{3}分",Name,Age,Gender,_Score); -->8 } public int Score { get {return _Score;} } } class Pregram { static void Main(string [ ] args ) { -->1 Teacher tea1= new Teacher ("张三 ",19,‘男‘,95); -->2 -->6 stu1.Hello(); Console.ReadKey(); -->9 } }
解析代码:
public Teacher(string name , int age ,char gender , int score)//定义子类构造方法
: base (name ,age ,gender) 调用父类方法 为什么不这样写 base (string name ,int age ,char gender) 因为name已经定义过了如果写string name 有类型和变量 这就是定义 而不是传参
base : 如果这里你不用base调用父类构造方法为子类赋初值,那你只有自己手动在子类构造方法里面为子类赋初值例子如下:
base._name-name; this._age=age; this.gender=gender;
注意:这里的base和this没区别 在字段前加base和this只要不会由编译器误解给程序走看的。
上面代码涉及构造方法(继承中)的执行顺序:
1.调用子类构造方法时,先调用父类构造方法 这里的base是在调用父类构造方法 base后面的参数 name,age,gender应该和4参数对应
2.private的限制 类里面class{}大括号范围
二.继承中关于构造方法的调用this和base区别
this : 表示当前类 ,表示当前构造方法 --》解析:指定先调用哪一个当前类的构造方法就一个类里面(变化在一个类)
base:表示父类,父类构造方法--》解析:指定首先调用哪一个父类构造方法(变化在子类和父类 俩个类或多个类)
构造方法不一样你创建出来的对象就是不一样
this代码示例如下:
class Myclass { public Myclass -->4 { Initiallomporrent(); -->此为标准的构造方法执行所有字段的初始化工作 } public Myclass (string n) : this () -->3 -->7 { Console.WriteLine(n); --》8 } --》9 private void IntialComent()......折叠代码 --》6 //此句是所有字段进行初始化 } class Program //先初始化窗体然后去扩展 { static void Main (string [ ] args ) { -->1 Myclass myclass=new MyClass("123"); -->2 -->10 } }
解析代码:
2 3 4 7 8 调用带有参数string n 这个构造方法之前 先去调用标准的构造方法
三 . 继承构造方法《1》
问题:在创建对象的时候就是调用类的构造方法进行初始化 因此在创建对象时,父类构造方法有没有被调用 怎么证明?
构造方法:
public 类名() //保证此时的方法名就是类名 保持一致 { //方法体 }
此时:构造方法没有返回值。可以添加参数,所以也就能重载 构造方法不能直接调用 除非只能 new。
class BaseClass { } class Subclass:Baseclass { } clsaa Program { static void Main(string [ ] args ) { SubClass sub=new SubClass();
} }
注意:
1. 此时class baseclass 与 class subclass 中看不到方法 不代表没有方法 如果此时你看到 那么new subclass()调用clsaa baseclass 与 class subclass 中的默认无参构造方法
2. 如果有需要 你就得手动添加构造方法
下面代码是证明过程:
证明:1. 如何看子类创建对象得时候,有没有调用父类构造方法
2. 如果你在父类中输出一句话,看到调用时打印这句话了没有
class BaseClass { public BaseClass():base() --》5 //base作用 调用object 只是你看不到 { Console.WriteLine("我是父类"); --》6 } } class SubClass:BaseClass { public SubClass ():base() -->4 -->7 { Console.WriteLine("我是子类"); -->8 } } class SubSubClass: SubClass { public SubSubClass: base() --》3 --》9 { Console.WriteLine("我是孙子类"); --》10 } } class Program { static void Main( string [ ] args) -->1 { SubSubClass sub =new SubSubClass(); -->2 -->11 Console.ReadKey(); --》12 } }
解析代码过程:
1. Main 方法开始执行
2.调用了创建对象得new SubSubclass()方法
2→3 跳到 SubSubclass()方法
3 执行了完成 但是没有执行consolle.writeline (“我是子类”)原因在于base 如果 此处没写base 系统也会默认这里有base因为此处有了base 所以3直接→4然后到5 这里的base作用是调用object 因为object 是所有成员得根类5→6 打印 我是父类 6→7按顺序开始执行了 7→8 开始打印 我是子类 8→9→10→11 这里的new subsubclass () 括号里没有参数 编译器默认添加得无参构造函数 你也可以手动添加 然后 →12 结束!
以上就是构造方法执行顺序 base();
注意:
1.在创建对象得时候,好像是先调用父类构造方法,在调用子类构造方法从5开始得 1→4 其实是先调用子类构造方法往上推到顶层在顺序下来。
2.在调用构造方法的时候,其实默认有一个base(),调用了父类无参得构造方法比如 4调用5 public BaseClass ()这个父类无参构造方法。
//自定义调用构造方法顺序 :默认是调用无参构造方法 但是你可以指定调用它得那个有参构造方法 class BaseClass { public BaseClass():base() --》如果此时在 public BaseClass( int i )添加参数 { Console.WriteLine("我是父类"); } } class SubClass:BaseClass { public SubClass ():base() //这里就会出错 因为这里调用默认的无参构造方法 { //此时有参数了 调不成 怎么破?解决方法如下1和2 Console.WriteLine("我是子类"); } } class SubSubClass: SubClass { public SubSubClass: base() { Console.WriteLine("我是孙子类"); } } class Program { static void Main( string [ ] args) { SubSubClass sub =new SubSubClass(); Console.ReadKey(); } } 解决方法一 就是手动添加一个无参构造函数 public BaseClass() { Console.WriteLine("我是父类"); } 解决方法二 就是用base直接传一个参数 但是里面传得参数必须和上面类型对应 上面是int型 所以这里传1 如果上面定义的是string 型 这里传 “1” public SubSubClass: base(1) { Console.WriteLine("我是孙子类"); }
隐藏基类方法 :父类和子类方法名相同 (完全相同得方法)
为什么要隐藏基类方法:因为只有这样 子类对象就知道该如何控制它访问自己得方法和父类得方法
代码示例:
Class 老公 { public void Func ()------->1 { Console.WriteLine("体贴"); } } Class 父亲:老公 { public void Func()-------->2 { Console.WriteLine(‘关爱‘); } } Class Program { Static void Main ( string [ ] args) { Object o = new 父亲(); o.Func(); ((父亲)o).Func(); ((老公)o).Func(); } } 此时如果1和2这样写 会出现异常1和2方法同名 如果有意隐藏,请使用关键字new 2 写成 public new void Func () 其实这里的new给编译器和程序员看的 不写一样
代码解析:
如果子类方法例如 public void Func()与父类方法 public coid Func()相同 那么调用时例如 o.Func()这时你调用谁?
很显然调用的是class 父亲中的 public void Func();因为当子类方法和父类方法同名时这时候就将调父类方法 例如 :
父类 class 老公 {public void Func () {}} 方法隐藏了 但是只是隐藏 不是消失 如果父类方法隐藏了 能不能调用呢?
解释:能调用 但是看类型 隐藏看类型 例如 ((父亲)o).Func(); 此时是父亲这个类型 ((老公)o).Func(); 此时类型是老公这个类型
里氏转换概念: 如果一个类型 它有父类 也有子类 那么子类的对象可以直接赋值给我的父类 是 赋值 。
代码示例 :
MyBase myBase = new MySub(); //new的一个子类对象 父类 子类 上面代码等同下面代码: MySub Sub= new MyBase(); MyBase mBase=Sub ; myBase.Func();
单例模式:
类似飞秋 一个电脑只能运行一个 但是QQ不一样 你可以登陆多个号码
代码示例:
Class Myclass { private static MyClsaa_default = null; -->1 //静态字段 public static MyClass Default --》2 { get { if (_default = null) -->5 { _default = new MyClass(); return _default; } else { return _default; -->6 } } } } (public) private MyClass ()//当这里的public 改成 private 的时候 你创建对象调用方法时会出现问题 因为有了private 限制 那么怎么办呢? { //解决办法就是 创建一个静态的字段 1 然后为1 写一个方法(或者属性) 2 } Class Program { static void Main (string [] args ) { MyClass myClass = MyClass.Default; -->3 Myclass myClass2=MyClass.Default; -->4 } }
代码解析:
1.当第一次运行3的时候 此时_default=null 所以执行 5 当运行4的时候 _default不等于 null 这时执行6 返回_default 其实就是第一次
重写基类方法实现多态 (里氏转换原则)
协议不是一个实实在在存在的东西,不应该能让一个协议去做什么事情或者做什么东西 是我们根据协议去做一些事情或者一些东西例如: USB协议 我们可以根据usb协议制作让手机传数据东西或者usb灯 让灯发光等等
加入Virtual 代表是虚 前面加了virtual这个方法就是虚方法也有方法体也可以调用例如: new Protoul ().usb();可以打印说明可以调用,为什么要加virtual在子类上 说明重写了基类方法 public virtual void usb();
在只有一个usb接口就是一个对象调用usb();这样一个方法根据这个usb()接口插上去这个东西是什么做相应的反应 例如;插上了usb灯 就发光 插上手机就传输数据 所以反应表现不一样 这就叫做 利用重写基类方法实现多态。
里氏转换原则:第一条 子类可以直接赋值给父类相当于将子类强制转化为父类对象
父类提供一个方法如果是虚的,那么子类可以将该方法重写只有子类前面加上一个override就叫做重写基类方法, 重写基类方法以后父类方法将不存在了,没有了,只剩下子类方法
口诀: new 则隐藏 override 重写 隐藏看类型 重写只管新
1. 一个对象处于不同的环境 表现出不同的特征 举例 :七匹狼广告
2.只管最新的那个重写方法 同一个父类它里面存在的是不同子类所表现出来不同子类的特征就是一个usb插口 插上的东西不同反应各不相同 追寻同一种协议
:这就是俩种实现多态的方式
我们的隐藏基类方法只管子类里面new就行了基类我不用去管 但是重写基类方法必须保证父类一定要virtual 如果父类不virtual不能重写 然后子类能override。
里氏转换原则:
1. 子类可以直接赋值给父类(子类可以直接转化为父类对象)
2.如果满足第一个条件的父类对象可以强制转化为原来的子类对象
代码举例:
protocal 为父类 iphone6为子类 第一条代码举例: Protocal = iphone6( Pro); 第二条代码举例: protocal = new iphone(); iphone6 i= ( iphone ).protocal; 里氏转换原则伪代码: 1. 父类 父类对象 = new 子类(); 第一条 2. 子类 子类对象 = ()父类对象; 第二条 存在前提 第一条成立 重写基类方法完整代码示例: Class Protocal { public virtual void USB() { Console.WriteLine(“我是大牛,我写的协议你要用吗?继承我吧”); } } Class Iphone6: Protual { public overide void USB() { Console.WriteLine(" 充电"); } } Class Light:Protual { public override void USB() { Console.WriteLine(“发光”); } } Class UDISC:Program { public override void USB() { Console.WriteLine("传输数据"): } } Class Program { static void Main(string [ ] args ) { new Light().USB(); new Iphone6().USB(); new UDISC().USB(); Console.ReadKey(); } } //因为插口只有一个所以: Protocal.protocal; protocal=new light; 着俩句代码等同 Protocal protocal=new light ();
属性
1.属性相关
面向对象:就是找个对象帮你做事儿。
描述对象 :行为 就是方法 特征 就是字段 通过字段描述 属性 :限制外界随便访问字段的一种方式
定义字段时比如 string mark ; 此时 默认访问级别为private
属性的演变过程代码如下:
Class 方便面 { private string mark; public void set_mark(string value )//只写 就是修改值 { mark=value; } public string get_Mark()//只读 就是读取 { return mark; } } Class Program { static void Main (string [] args) { 方便面 f = new 方便面 (); f.set_Mark(‘康师傅红烧牛肉面‘); Console.WriteLine( f.get.Mark () ); } } //这俩个方法虽然能完成要求 但是麻烦 所以就简化了 public string Mark() { get{ return mark ;} set{ mark = value ;} } 用反编译(神器)IL代码 看出属性的本质就是方法 属性不能存储数据 字段才能存储 自动属性 : public string Zidongshuxing { get; set; }
构造方法也有重载 有重载就考虑到调用 怎么调用 this 就出现了 当前类中(this)
this: 当调用 指定构造方法后有this的时候
public Constructure (): this () { } 这时先执行this(“1”)然后才是 public Construeture()
有继承关系默认调用父类构造函数 (无参数的那个)
如果此时父类构造方法有参数就回出错 这时手动添加无参构造方法或者传入参数也可以指定调用
为社么要隐藏基类或者重写基类因为当你继承时有new了对象 当调用方法时 默认会调用父类而此时你的父类方法不是你需要的,你需要 子类方法,这时你得跳过父类方法那么只能把父类方法隐藏或者让它消失。
IS 运算符用法
is关键字表示 判断 person [ i ] is chinese 左边对象 和右边对象是不是相等 就是判断Person 【i】能否强转位 chinese 这种类型 如果强转成功返回True 失败则返回 false 代码示例如下:
Class TTT { } Class Program { static void Main (string [ ] args ) { TTT t = new TTT(); //成功 bool b = t is object ; //此时是true 所以强转 bool b=t is string ; //此时是false 强转失败 } } 代码示例2: Class TTT { } Class BBB:TTT { } Class Program { static void Main (string [ ] args ) { TTT t = new TTT(); bool b = t is BBB; //如果这里强转失败 则是false; 失败原因不符合里氏转换原则 TTT t = new BBB(); bool b = t is BBB();//如果这时是true 强转成功 } } //这就是IS的用法 就是看左边能不能转成右边 看返回true还是false
AS运算符:
My temp = myBase(对象) as MySub(类型); 如果此时MyBase能转换位MySub转换好了 就把值赋给temp 如果不能转换我就给temp=null; 但是is判断 myBase is MySub; 表明它能不能判断返回的是true还是false。
多态 为了程序可扩展性:
开放封闭原则 对扩展开放 对修改封闭(访问修饰符的体会)
多态 重写经典范例 : Tostring
多态与Tostring()方法 Tostring 对类型有很重要的意义 任何类型都具备Tostring 方法原因是object是根类提供了Tostring()方法 但是要注意Tostring是虚方法
代码如下:
//默认将你输入类型的名字打印出来只输出类型名 Class MyClasss { public string Name1; public string Name2; public string Name3; public override string Tostring () { return Name1+Name2+Name3; } Struct MyStruct { public string Name ; public override string Tostring () { return “哈哈哈”; } } } Class Program { static void Main ( string [ ] args ) { string [ ] str ={ "1", "2", "3", "4",}; Myclass myclass= new MyClass(); myClass.Name="我是myclass"; Mystruct myStruct; mystruct name="我是mystruct"; Console.WriteLine( str ); → str.Tostring(); Console.WriteLine( myclass ); → myclass.Tostring(); Console.WriteLine( mystruct ); } } //这些代码就是默认调用Tostring方法。 此时只能输出类型。不过你写了Tostring()方法在构造类型中就可以自定义打印 // public override string Tostring () // return
多态的使用 :将不同对象都当作父类来看屏蔽掉各个对象间的不同 写出通用代码做出通同编程 以适应需求变化
通俗讲: 我设计一个USB协议或者我做一个usb接口 你所有的厂商生产usb产品时 不管u盘也好 mp3也好还是其他的你只要符合我这个接口标准我就可以拿来用你是什么东西我就会实现什么东西
多态: 前提条件 :是方法签名必须相同 多态的保障: 1 继承 2 里氏转换原则
is 和 as 判断父类继承 判断接口实现 判断拆箱与装箱 多态的实现2 抽象类 Abstract
抽象类 抽象方法
class Protocal (协议)
{
public void USB ()
{
}
}
此时 对于协议而言不是一个具体的东西比如类是车模当实例化类时就是把车模做成一个汽车 就是对象了 但是方法是对象得行为此时这个协议无法实例化为对象时(没有具体的对象 谈何对象得行为) 方法体就写不出来 只有俩个大括号
所以
public void USB () { }
此时大括号空着 当以当重写时这里就得加一个virtual 变成
public virtual void USB() { }
当这个方法无法写出方法体时 大括号就没有意义所以就不写了 变成 public virtual void USB ()
但此时不符合方法的语法就会出错 语法错误 由于此时父类无法实例化为对象没有对象得行为就是方法 所以此时方法写不出来或者此时也不需要实例化或者是不知道怎么样实现 比如动物兔子得叫声 你不能写成兔子吧 所以就出现了解决这个问题得方法Abstract
此时代码变为 public abstract void USB()//表示一个抽象得方法就不用写方法体了;此时就不会出现因为方法语法问题而出错
一个类型只有一个方法 当这个类型实例化为对象得时候就会调用类的构造函数对对象赋值但是这时无法实例化怎么调用这个抽象方法呢所以此时只得在类前面加abstruct 表示 抽象类 代码示例:
abstruct class Protocal { }
没有方法体得方法→抽象方法→用abstruct修饰 包含抽象方法得类必须是抽象类 不能实例化得类→抽象类 抽象类中可以包含非抽象成员 代码如下:
abstruct class Protocal { public abstruct void Protocal public void Func() --------->正常方法不是抽象得 它是为子类服务得 就是说子类可以调用它 { Console.WriteLine(“Function”); } } //那么如何调用抽象方法呢! Protocal p= new Iphone (); P.USB(); P.USB(); 用法上完全和重写virtocal一样 就是语法上要求多一点 如果变成 public abstruct void USB () { //空实现 } //这样也不对 虽然你没有写方法体(实现体)但是有大括号在表示 空实现
抽象类里可以包含非抽象成员就自然包括字段自然也就有初始化过程 这不就需要构造函数了 因为构造函数得作用就是初始化 所以有构造方法 只不过不能被外界调用所以一般把抽象类得构造方法一般设为private 或者 protect 使其受到保护
抽象类依旧是描述对象得模版 :
1. 抽象类可以有非抽象成员
2.抽象类不能实例化
3.抽象类存在就是为了被继承 因此不能设为private
4.抽象方法就是为了让子类重写
注意:抽象类不能实例化 比一般类 多 抽象成员 代码如下 :
案例:动物 animal 都有 Bark (叫声)方法,但是猫和狗叫声不同 。 shift + ait +f10 自动添加虚方法代码 abstruct class Animal { public abstruct void Bark (); } class Dog; Animal { public override void Bark(); { Console.WriteLine("汪汪汪"); } } class Cat ; Animal { public abstruct void Bark() { Console.WriteLine("喵喵喵"); } } class Program { static void Main (string [ ] args ) { Animal al = new dog (); al.Bark(); Animal a2; ----------------》这种写法是因为父类只能new一个对象所以得换了方式只能这样写 Cat c = new Cat (); a2=c ; a2.Bark(); Console.ReadKey(); } }
自动属性就是为了方便程序员 简化 操作
正常属性执行过程:
class MyClass { private string test ; public string Test; { get { return text ;} 7 set { test = value ;} 3 4 } } Class Program { static void Main (string [ ] args ) { 1 MyClass class1=new MyClass(); 2 Class1.Test =“123”; 3 5 Console.WriteLine(class.Test); 6 8 } } // 2创建对象 3 赋值得时候实际上是调用得set()方法,相当于把2123传给→value 然后value再把值传给text 当进行到6得时候就是打印属性 此时访问get方法就到7 这整个过程就叫做属性的读取与赋值 自动属性 得执行过程和上面一样自动属性得数据存在哪里了存在后台(BackingField里面)反编译可以看到
用什么属性视情况而定
抽象属性
abstruct Class MyBase { public override string Test { get; //只读得抽象属性 set; } } Class MySub : MyBase { string Test; public override string Test { get text ; } } //整个过程得含义就是 抽象类定义一个只读得属性然后再子类里面提供字段并实现得这个过程就是以上代码(抽象的属性用法)
抽象属性:难点1 比较绕
//抽象属性代码 abstruct class MyBase { public abstruct string Test { get ; set; } } //下面边自动属性了 Class MySub :myBase { public override string Test { get; set; } } //这里的自动属性等价于你单独重新生成一个变量得属性 注意此时不要受override影响
抽象属性难点2 :
abstruct class MyTest { public abstract string Test { get;//次世代吗就会报错 因为无法重写得原因是父类没有提供set访问而你下面的子类有set所以会出错 } } Class MyTestSub: MyTest { string str; public override string Test { get { return str;} set( str =value ;) } }
抽象成员: 1 方法 2 属性(属性其实也是方法) 3 索引器 (本质是带参数得属性)凡事方法就可以抽象 凡是方法相关得都可以抽象 除此之外全部砍掉 4 时间得声明 (可以看做属性)
自动属性里面的set 和get 必须成对出现 缺一不可 因为它是对字段自动生成你知道那个字段的所以只能有get读 set 写缺一不可 自动属性得特点
抽象属性 使用的时候 一般是抽象类提供属性 及可访问性 这里的抽象类指抽象父类 子类提供字段与属性的实现 抽象属性中get set 不用成对出现
接口语法
interface (接口关键字)+ IDoirable(接口名字) { } interface IDrivable { } //接口就是一个类型 大部分情况下 默认第一个字母为I 接口也是为实现多态
类是对具体事物的抽象 诺记手机5180
抽象类是对一类具体事物的抽象 手机
接口是对一个能力的 抽象 打电话
接口定义能力即方法由子类进行实现 接口的存在就是为了实现多态 接口可以实现多继承 就是可以继承多个接口
类的定义一般格式:
[public ] [static ] class 类名:[基类名] [ [ 接口名] ,接口名] { //成员 }
由于接口可以实现多继承所以就解决了继承体积庞大的问题
接口语法注意:
命名一般使用I开头
成员没有访问修饰符
无实现体
派生类必须实现接口方法 除了抽象类
接口成员必须抽象
为什么要有显式实现接口 为了避免方法重名
实现方式 接口名.方法名()
显式实现的方法只有接口对象才能调用
面向对象编程尽量尽可能使用抽象数据不是用具体数据 因为可以实现多态比较灵活
一般定义执行过程 接口 抽象类 父类 子类 的顺序 一般先定义接口 再定义抽象类
注意: 避免定义 体积庞大 功能齐全的接口 因为使用简单的结构框架方便灵活调用 单一原则 一个接口只描述一个功能 接口组合使用
抽象类和接口的区别:
抽象类适用于一系列并且有需要继承的成员 →USB协议
接口适用于不同系列的类相同的动作 → 功能
对于不是相同的系列但具有相同的行为这个据考虑接口
值类型 值得传递 数据存储再堆栈 → 复制文件 →valuetype→ object
引用类型 先创建对象再传值→ 创建快捷方式 不管你创建多少个快捷方式对象指向只有一个 →object
参数的传递 ref 和out :ref和out都可以实现参数传递的时候在方法内修改的参数结果再外界受到影响
注意:使用ref和out都可以将参数传入方法并保留再方法中对参数赋值时的影响
即参数再方法中被修改了方法结束后结果仍然保留方法中最后一次被修改的值这就是引用传递
ref reference 引用 引用表示方法中的是变量得引用就是快捷方式 使用前要赋值 把数据传进去
out 参数用来输出 即方法中对变量得修改就是为了让其输出到外边得 使用后要赋值 把数据传出去
params:
一个方法只能有一个params参数(传进去)并且只能是最后一个位置
static void Main ( string [ ] args) { int [].nums={1, 2, 3}; Func (111,nums,10,20,30); } static void Func (int i ; int [ ] nums ,params int [ ] ) { } //传参数得是偶 int i 对应 111 int[ ] nums 对应 nums 剩下得10 20 30 全部被params打包传递 所以params参数就是最后一个位置并且每个方法仅有一个params
静态成员与实例成员 表示 static 表示它修饰得这个成员叫做静态成员
就是那些为了让你使用方便而且频繁出现得东西为了下次还能使用static修饰它就不会被垃圾回收下次你要是用了直接调用他们 空间都分配在静态储存区
静态成员作用于整个应用 程序不受clr(运行库)得控制 不会垃圾释放掉
如何定义静态成员 static 如何调用 与实例成员调用关系
定义 :
public static int num;
调用 : (类名.成员名)
静态类方法中不能直接调用非静态成员 也就是实例成员
静态成员属于整个类型 实例成员属于某个对象
对静态成员得访问会将结果保留下来 谁都能访问
静态类 当你这个类里面全是静态成员得时候 静态类只能包含静态成员
性质修饰:static 与abstruct 级别相同 只能用一个 与public 与 internal 没有关系 所以这是俩码事。
静态成员属于所有类 非静态成员属于当前实例 静态类的生命周期从第一次使用开始到程序结束 因此尽量少用(占内存)
try { //可能出现异常得代码 一旦出现异常得代码 就跳到catch try中其后得代码就不执行了 } catch { //一旦出现异常就执行这里代码 记录出错 } finaly { //释放资源 无论是否出现异常都执行finaly里面代码 }
异常一个是一个类 需要抛出异常就要new throw 运算符 抛出异常