zoukankan      html  css  js  c++  java
  • Delphi高手突破第二章(3),封装,继承,多态


    ==============================封装======================================
    封装目的:把可变部分与稳定部分分离开来。将稳定部分暴露给其它块,而将可变部分隐藏起来,以便随时让它改变。

    Object Pascal中,实现了两个级别的封装:类级和单元级

    类级别的封装:
    published与public差不多,区别在于published的成员可以被Delphi开发环境的Object Inspector所显示。
    所以对于外部类,public和published是对外界的接口;对于派生类,接口是public和published和protected的集合,只有private是内部细节。

    单元级的封装:
    1. 在一个Unit中声明的多个类,互为友元类(可相互访问private数据)
    2. 在一个Unit的interface部分声明的变量为全局变量,其它Unit可见
    3. 在一个Unit的implementation部分声明的变量为该Unit的局部变量,只在该Unit可见
    4. 每个Unit可有单独的初始化段(initialization)和反初始化段(finalization),可在编译器支持下自动进行Unit级别的初始化和反初始化。


    Object Pascal的单元文件被分为两个部分:interface和implementation
    如同类的封装一样,Unit的这两部分分别为接口和实现细节。因此interface部分对外是可见的,声明中interface段中的所有函数、过程、变量的集合,都是单元文件作为一个模块的对外接口。而Implementation部分是对外隐藏的。

    而为单元文件提供初始化和反初始化机制,即保证了单元的独立性,由此可以脱离对其它模块的依赖。其作用类似于类的构造函数和析构函数。


    定义接口的规则:
    1. 保证接口是功能的全集,即接口能够覆盖所有的需求
    2. 尽量让接口是最小冗余的,有利于客户的学习和使用。
    3. 接口是是稳定的。能保护客户的代码在细节改变的情况下,不随之改变。

    绝大多数失败的设计,都来自于失败的封装。

    ==============================继承======================================
    定义继承关系:
    TB = class(TA)

    Object Pascal只支持C++中所谓的public继承:
    public还是public,protected还是protected,private依然被继承为private!!!!
    public在语义上严格奉行“是一种”关系,也就是说类B若派生自类A的话,那么在任何时候,都可以称“B是一种A”。
    如果B不是在任何时候都可以当作A,那么不可以将B从A中派生。
    这句好像是错的(明明可以访问):即使派生类对象无法访问基类子对象中的private数据,它们依然存在并占用内存空间的,无法访问它只是因为编译器为它做了额外的保护。

    举例:
    type
    TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
    end;

    TMyClass0 = class
    private
    str:String;
    end;

    TMyClass = class(TMyClass0)
    Public
    FMember1 : Integer;
    FMember2 : Integer;
    FMember3 : WORD;
    FMember4 : Integer;
    Procedure Method();
    End;

    var
    Form1: TForm1;

    implementation

    {$R *.dfm}

    procedure TForm1.Button1Click(Sender: TObject);
    var
    Obj : TMyClass;
    begin
    Obj := TMyClass.Create();

    Obj.str:='dddddddd';
    with memo1.Lines do
    begin
    Add('对象大小:' + IntToStr(Obj.InstanceSize));
    Add('对象所在地址 :' + IntToStr(Integer(Obj)));
    Add('str 所在地址:' + IntToStr(Integer(@Obj.str)));
    Add('FMember1所在地址:' + IntToStr(Integer(@Obj.FMember1)));
    Add('FMember2所在地址:' + IntToStr(Integer(@Obj.FMember2)));
    Add('FMember3所在地址:' + IntToStr(Integer(@Obj.FMember3)));
    Add('FMember4所在地址:' + IntToStr(Integer(@Obj.FMember4)));
    end;
    ShowMessage(obj.str);

    Obj.Free();
    end;


    Object Pascal只支持单继承,保证每个派生类都只有唯一一份基类子对象。


    多态置换原则:A如果不能无条件出现在B的位置上取代B,那么不要把A设计成B的派生类。
    举例:请给我一个水果(可以替换成给他一个苹果,没有问题)

    悖论(容器问题):当A是B的一种时,那么A的容器绝对不是一种B的容器!
    举例:水果袋可以放任何水果(不能替换成给他一个苹果袋,这个结论是错误的)


    数学上,圆是椭圆的一种;OOP却说,圆不是一种椭圆,原因在于椭圆拥有的能力已经无法完全包含在圆所拥有的能力中(x和y必不相等),这时就无法满足“多态置换原则”。失败原因在于,让基类拥有了太多的额外能力,哪怕仅仅是一个函数方法(个人解决方案:可以把椭圆的SetSize设置为私有方法)。“是一种”关系,是“普遍”和“特殊”的关系,记住总是要弱化基类,强化派生类。


    ==============================多态======================================
    OOP的三大特征:封装可以隐藏细节(封装到类和函数里),继承可以扩展已有的代码模块,它们的目的都是代码重用。而多态则是为了另一个目的:接口重用。


    一个抽象的指令,可以让每个个体完成具有同一性质但不同内容的动作,多神奇啊!

    多态性允许用户将派生类的指针赋给基类类型的指针。多态性是通过虚方法(Virtual Method)实现的。
    虚方法就是允许派生类重新定义的方法。派生类重新定义基类虚方法的做法,称为“覆盖”(override)。

    多态的实质:
    1. 在运行期间动态地调用属于派生类的虚方法
    2. 允许父对象设置成为与一个或更多的它的子对象相等的技术;赋值之后,父对象就可以根据当前子对象的特征以不同方式运作。

    procedure fly(); virtual; abstract; // 纯虚方法
    凡是含有abstract方法的类被称为“抽象类”,永远无法创建抽象类的实例对象。抽象类是被用来作为接口的。

    VCL类库中,TObject有一个虚拟的Destroy析构函数和一个非虚拟的Free方法。
    对于析构函数必须加上override关键字(跟其它虚函数的使用方法一样):destructor Destroy(); override;
    否则的话(不加override关键字),父类指针调用的是父类自己的析构函数,这就出问题了:父类的析构函数压根不认识子类的具体元素,怎么可能正确销毁呢。

    重载(overload)是指定义多个同名函数,但参数不同:
    function func(p:integer): integer; overload
    function func(p: string): integer; overload
    注意:它们的调用入口地址在编译期间已经静态确定了!重载只是一种语言特征,与面向对象无关。

  • 相关阅读:
    2014.12.31今年最后的一天
    leetcode11 盛最多水的容器(Medium)
    leetcode23 合并k个排序链表(Hard)
    leetcode148 排序链表(Medium)
    leetcode48 旋转图像(Medium)
    leetcode227基本计算器II (Medium)
    leetcode338 比特位计数(Medium)
    leetcode32 最长有效括号(Hard)
    leetcode面试题10.01 合并排序的数组(Easy)
    leetcode55 跳跃游戏(Medium)
  • 原文地址:https://www.cnblogs.com/findumars/p/2629562.html
Copyright © 2011-2022 走看看