C#面向对象编程(三)

来源:互联网 发布:怎么检查网络被盗用 编辑:程序博客网 时间:2024/06/03 18:20

5 封装

  1. 类类型
    由字段数据(成员变量)及操作这个数据的成员(构造函数,属性,方法)所构成的自定义类型
    object 对象: new关键字创建的某个类类型的实例
    new new关键字把引用赋给对象
    fields 字段: 在类中定义的变量
    properties 属性: field 加上其get/set方法
    members 成员: 字段,属性,方法,类的事件

  2. 构造函数
    在创建对象的同时创建其状态.本质上是类的特殊方法,名字和类名一致但是永远不会有返回值(void)
    构造函数可实现重载.
    默认构造函数: 没有参数的构造函数
    会将字段数据都设置为正确的默认值,一旦自定义构造函数,编译器就取消自定义构造函数
    实现为空的默认构造函数会为字段数据都设置为正确的默认值

  3. this
    提供对当前类实例的访问.
    可用来解决入参名字和 类型数据字段的名字相同产生的作用域歧义
    可用来串联构造函数链(可被可选参数代替)
    可以设接受最多参数个数的构造函数为“主构造函数”并实现必须的验证逻辑.其余的构造函数可以使用this把入参转发给主构造函数,先执行主构造函数,后执行调用构造函数的代码
    // Constructor chaining.
    public Motorcycle() {}
    public Motorcycle(int intensity)
    : this(intensity, "") {}
    public Motorcycle(string name)
    : this(0, name) {}
    // This is the 'master' constructor that does all the real work.
    public Motorcycle(int intensity, string name)
    { ... }
  4. static
    static可用来定义静态成员,静态成员直接从类级别而不是对象引用调用
    static可应用于:类,构造函数,类的数据,方法,属性
    静态数据字段:由所有对象共享,一旦发生改变,所有对象关注同一个内存位置.但是类创建新实例时,会被重写.
    静态方法:静态方法可以直接通过类名进行访问
    静态构造函数:
    不可重载,不可修饰,不接受参数
    只执行一次,用来设置静态字段,可以用来维持静态数据的值
    执行优先级高于任何实例级别的构造函数
    静态类:又称为工具类.
    不能通过new来创建,成员必须用static关键字标记
  5. 面向对象的3个原则
    封装 隐藏对象内部的实现及保护数据完整性
    继承 促进代码的重用
    包含/委托模型(聚合):类a定义类b的成员变量,并向用户间接公开b的功能
    多态 用相似的方式处理相关的对象
  6. 访问修饰符
    默认情况下,类中的成员是private,类是internal
    public 派生类及外部程序集均可访问
    private 只能在定义类或结构中使用
    protected 只能在当前程序集中使用
  7. Encapsulation
    核心是对象的内部数据不应该从对象实例直接访问.如果调用者想改变对象状态,就要间接使用公共成员,公共成员(setter/getter)可以实现数据保护
    定义私有字段的方式
    set/get
    private string empName;
    public string GetName()
    {
    Console.WriteLine("GetName Get");
    return empName;
    }
    public void SetName(string Name)
    {
    Console.WriteLine("SetName Set");
    this.empName = Name;
    }

    定义.net属性,并不会调用传统的方法
    value表示调用者设置属性时传入的值,是上下文关键字
    优势: 属性校验放在属性方法中,对属性设置时调用属性方法,可以减少代码复用.
    private string empName;
    public string Name
    {
    get { Console.WriteLine("GetName Getter"); return empName; }
    set { Console.WriteLine("SetName Setter"); empName = value; }
    }
  8. 自动属性
    只是获取和设置值,不需要实现任何逻辑.必须同时支持读写功能,不能设置访问权限.
    会为字段数据提供默认值,但是类实例属性默认为null
    设置只读自动属性
    public string AutoName { get; private set; }
  9. 对象初始化语法
    跳过构造函数为实例的属性赋初值
    //object initialization syntax
    Person pInitiaSyntax = new Person { Name = "default", Age = 22 };
    Emploee eInitiaSyntax = new Emploee { saccount = new SavingAccount(12) };
    //default constructor
    Person pInitiaSyntax2 = new Person() { Name = "default", Age = 22 };
  10. 常量数据
    const 赋初始值后不再改变.默认是隐式静态的,并且必须赋初始值.
    readonly 同样赋值后不能再改变.但是可以在运行时设置,在构造函数中赋值是合法的
    public const bool IsCarbonBased = true;
    public readonly bool strReadOnly = true;
  11. 分部类型
    partial 将一个类分部到多个C#文件中
    the this keyword can be used to obtain access to the current object, the static keyword allows you to
    define fields and members that are bound at the class (not object) level, and the const keyword (and
    readonly modifier) allows you to define a point of data that can never change after the initial
    assignment.

6 继承和多态

Inheritance 继承: 构建一组相关类,允许我们重用父类中的通用功能
Polymorphism 多态: 虚成员和抽象成员在类层次结构中创建

  1. 继承的机制
    代码重用: 继承 is-a 和 包含/委托模型 has-a
    class MiniVan : Car {}
    派生类不会继承父类的构造函数,构造行数仅用于在内部定义的类
    C#要求类只有一个直接基类,但可以有多个接口
    seal: 用来防止发生继承
    seal class MiniVan : Car {}
  2. 继承
    base关键字挂接构造函数方法,派生构造函数将数据传递到最近的父构造函数中
    base也可用于子类访问父类定义的public和protected成员
    public Emploee(string name):base(name) { Console.WriteLine( base.strProtected); }
    protected: 用来定义只能被派生类型使用的方法.直接访问实例的protected成员是不合法的
  3. 包含/委托
    委托就是增加公共成员到包含类,以便使用被包含对象的功能
  4. 多态 polymophism
    方法重写:子类重写基类定义的方法
    虚方法: virtual标记的方法,基类希望子类可以重写的方法.
    重写虚方法: override关键字
    class Person { public virtual void EatFood() { }}
    class Emploee : Person { public override sealed void EatFood(){ base.EatFood();} }
    抽象类 用来定义抽象的实体,abstract
    抽象类不可以被实例化
    抽象方法是纯粹的协议,只是定义了名字和返回值和参数.没有默认实现,必须被子类实现
    可以用抽象基类变量来保存任何指向子类的引用
    成员投影
    投影:逻辑上和重写相对的功能. 如派生类定义的成员和基类中的成员一致.
    可以通过添加new关键字来隐藏父类的版本.
  5. 基类/派生类的转换规则
    .net平台中最高基类是System.Object.Object可以保存任何类型的实例
    隐式转换:基类引用中保存派生类型,而这总是安全的.
    as: as关键字可以在运行时快速检测某个类型是否和另一个兼容,不兼容就返回null
    is: is也在运行时检测传入的基类类型,不兼容会返回false
  6. 超级父类: System.Object
    核心实例方法
    Equals() 默认比较是否指向内存中同一个项.即比较对象引用
    ValueType会重写为比较对象的内部状态值(基于值得语义)
    Finalize() 在对象销毁之前释放所有分配的资源
    GetHashCode() 返回int来标志指定的对象实例. string返回的值同int
    ToString()
    GetType()
    MemberwiseClone()

7 结构化异常处理 structured exception handling

  1. 是一种标准的用来发送和捕获运行时错误的技术
    分类:
    bug 程序员一方引起的错误. web编程中缺少对地址重定向的限制
    用户错误 有运行程序的用户引起的. 在文本框中输入非法格式的字符串
    异常 运行时的非正常情况. 打开已损坏的文件

    SEH统一了.net领域各种编程语言,提供了一种通用的方式来处理错误.
    不再通过数字常量来确定问题.异常中包含问题描述信息和调用栈的详细快照

  2. 四要素
    包含异常的类及其详细信息
    抛出异常的实例成员
    抛出异常的成员代码
    调用异常的成员的成员代码

    System.Exception: now time is 10/19/2017
    at ConsoleApp.Program.Test.ExceptionThrow() in D:\Git\SourceCode\C#\ConsoleApps\ConsoleApp\Program.cs:line 68
    at ConsoleApp.Program.ExceptionMethod() in D:\Git\SourceCode\C#\ConsoleApps\ConsoleApp\Program.cs:line 38

    捕获异常

    try
    {
    throw new Exception(string.Format("now time is {0}", DateTime.Now.ToShortDateString()));
    }
    catch (Exception e)
    { Console.WriteLine(e); }
    finally
    {
    Console.WriteLine("throw an exception , end");
    }
  3. 配置异常的状态
    targetsite
    stacktrace
    helplink
    data
  4. 系统级异常
    .net平台引发的异常称为系统异常, 基类是 SystemException>Exception>Object
  5. 应用程序级异常
    自定义异常应该派生自 ApplicationException>Exception>Object
    自定义异常是实现Exception的类,try/catch会捕获对应的异常
    自定义异常需要
    继承自ApplicationException/Exception
    有标记[System.Serializable]
    定义默认构造函数
    定义继承Message,内部异常,处理类型序列化的构造函数
  6. 处理多个异常
    最前面的catch捕获最特别的异常,最后的一般是System.Exception
    catch中可以再次引发一个异常
    finally块并不必须要有,是为了保证不管是否发生异常,总有一组代码会被执行

8 接口

  1. 接口类型
    一组抽象成员的命名集合.
    接口是纯粹的协议,不提供默认的实现.表示某个类或结构可以选择去实现的行为.
    Interface VS Abstract
    Interface 只能包含抽象成员,接口实现必须全部实现
    Abstract 抽象父类创建的多态接口只有派生类型才能支持
  2. 对象级别调用接口成员
    一个类型实现多个接口,根据as/is判断调用方法

                Emploee emp = new Emploee();            ITest it = emp as ITest;            emp.Print();            if (it != null)                it.SubPrint();            if (emp is ITest2)                emp.SubPrint2();
  3. 接口作为参数
    public void CallIterface(ITest it){}
  4. 接口作为返回值
  5. 接口类型数组
    如果有一个给定接口类型的数组,那么这个数组可以包含实现了该接口的任何类或是结构
  6. 显示接口实现
    解决多个接口类中包含相同方法的情况
    returnType InterfaceName.MethodName(params){}
  7. 设计接口层次结构
    适合的情况
    单层结构但是只有派生类的子集有公共的行为
    多层结构的类有公共的行为且公有的基类只有System.Object
  8. 构建可枚举类型
    实现IEnumerable
    对已经实现IEnumerable或IEnumerator接口的类,可以直接调用GetEnumerator
    yield 关键字用来向调用方的foreach结构指定返回值.当到达yield return 语句后,当前位置被保存下来,下次调用迭代器会从这个位置开始执行
  9. 构建可克隆的对象
    实现ICloneable
    class CloneClass : ICloneable
    仅包含值类型或结构可以用this.MemberwiseClone()(浅复制)或Clone()
    如果有一个保存其他引用类型的自定义类型,需要建立考虑每个应用成员变量的新对象
  10. 构建可比较的对象
    实现IComparable
    class CompareClass : IComparable
    IComparable.CompareTo(object obj)
原创粉丝点击