zoukankan      html  css  js  c++  java
  • 类的组合与继承

    定义两个类,一个是person,一个是family;在family类中创建person类中的对象,把这个对象视为family类的一个属性,并调用它的方法处理问题,这种复用方式叫:“组合”。

    类与类之间有一种父与子的关系,子类继承父类的属性和方法,称为继承。

    在继承里,子类拥有父类的方法和属性,同时子类也可以有自己的方法和属性。

    <?php
    class person{
        public $name;
        public $gender;
        public function say(){
            echo $this->name,"	is",$this->gender,"
    ";
        }
    }
    class family{
        public $people;
        public $location;
        public function __construct($p,$loc){
            $this->people = $p;
            $this->location = $loc;
        }
    }
    $student = new person();
    $student->name = 'Tom';
    $student->gender = 'male';
    $student->say();
    
    $tom = new family($stduent,'peking');
    print_r($tom);
    
    /*
     family object
     {
        [people] => person object
            {
                [name] => Tom
                [gender] => male
            }
    
        [location] => peking
     }
     
    */
    组合示例
    <?php
    class person{
        public $name = 'Tom';
        public $gender;
        static $momery = 10000;
        public function __construct(){
            echo '这里是父类';
        }
        public function say(){
            echo $this->name,"	is",$this->gender."
    ";
        }
    }
    class family extends person{
        public $name;
        public $gender;
        public $age;
        static $monery = 10000;
        public function __construct(){
            parent::__construct();    // 调用父类构造方法
            echo '这里是子类',PHP_EOL;
        }
        public function say(){
            parent::say();
            echo $this->name,"	itle	",$this->gender,",and is	",$this->age,PHP_EOL;
        }
        public function cry(){
            echo parent::$momery,PHP_EOL;
            echo self::$momery,PHP_EOL;    //调用自身构造方法
        }
    }
    $poor = new family();
    $poor->name = 'Lee';
    $poor->gender = 'female';
    $poor->age = 25;
    $poor->say();
    $poor->cry();
    继承示例

    在继承中,用 parent 指代父类,用 self 指代自身。使用“::”运算符(范围解析操作符)调用父类的方法。“::”操作符还用来作为类常量和静态方法的调用,不要把这两种应用混淆。

    组合与继承都是提高代码可重用性的手段。在设计对象模型时,可以按照语义识别类之间的组合关系和继承关系。

    通过一些总结,得出了继承是一种“是,像”的关系,而组合是一种“需要”的关系。

    利用这条规律,就可以很简单地判断出父类与儿子应该是继承关系,而父亲与家庭应该是组合关系。还可以从另一个角度看,组合偏重整体与局部的关系,而继承偏重父与子的关系。

    然而在编程中,继承与组合的取舍往往并不是这么直接明了,很难说出二者是“像”的关系还是“需要”的关系,甚至把它拿到现实世界中建模,还是无法决定应该是继承还是组合。

    那应该怎么办呢?有标准吗?有的,这个标准就是“低耦合”。

    耦合是一个软件结构内不同模块之间互连程度的度量,也就是不同模块之间的依赖关系。

    低耦合指模块与模块之间,尽可能地使模块间独立存在;模块与模块之间的接口尽量少而简单。

    解耦是要解除模块与模块之间的依赖。

    按照这个思想,继承与组合二者语义上难以区分,在二者均可使用的情况下,更倾向于使用组合。为什么呢?继承存在什么问题吗?

      1.继承破坏封装性

        比如,定义鸟类为父类,具有羽毛属性和飞翔方法,其子类天鹅、鸭子、鸵鸟等继承鸟这个类。显然,鸭子和鸵鸟不需要飞翔这个方法,但作为子类,它们却可以无区别的使用飞翔这个方法,这显然破坏了类的封装性。而组合,从语义上来说,要优于继承。

      2.继承是紧耦合的

        继承使得子类和父类捆绑在一起。组合仅通过唯一接口和外部进行通信,耦合度低于继承。

      3.继承扩展复杂

        随着继承层数的增加和子类的增加,将涉及大量方法重写。使用组合,可以根据类型约束,实现动态组合,减少代码。

      4.不恰当地使用继承可能违反现实世界中的逻辑

        比如人类作为父类,雇员、经理、学生作为子类,可能存在这样的问题,经理一定是雇员,学生也可能是雇员,而是用继承的话一个人就无法拥有多个角色。这种问题归结起来就是“角色”和“权限”问题。在权限系统中可能存在这样的问题,经理权利和职位大于主管,但出于分工和安全的考虑,经理没有权利直接操作主管所负责的资源,技术部经理也没权限直接命令市场部主管。这就要求角色和权限系统的设计要更灵活。不恰当的继承可能导致逻辑混乱,而实用组合就可以较好地解决这个问题。

    当然,组合并非没有缺点。在创建组合对象时,组合需要一一创建局部对象,这一定程度上增加了一些代码,而继承则不需要这一步,因为子类自动有了父类的方法。

    继承最大的优点就是扩展简单,但是其缺点大于优点,所以在设计时,需要慎重考虑。

    • 精心设计专门用于被继承的类,继承树的抽象层应该比较稳定,一般不要多于三层。
    • 对于不是专门用于被继承的类,禁止其被继承,也就是使用 final 修饰符。使用 final 修饰符既可防止重要方法被非法覆写,又能给编辑器寻找优化的机会。
    • 优先考虑用组合关系提高代码的可重用性。
    • 子类是一种特殊的类型,而不只是父类的一个角色。
    • 子类扩展,而不是覆盖或者使父类的功能失效。
    • 底层代码多用组合,顶层/业务层代码多用继承。底层用组合可以提高效率,避免对象臃肿。顶层代码用继承可以提高灵活性,让业务使用更方便。

    继承并非一无是处,而组合也不是完美无缺的。如果既要组合的灵活,又要继承的代码简洁,能做到吗?

    这是可以做到的,譬如多重继承,就具有这个特性。多重继承里一个类可以同时继承多个父类,组合两个父类的功能。

    可是多重继承太复杂了,那么还有其他方式比较好地解决这个问题吗?PHP5.4引入的新的语法结构Traits,可以方便我们实现对象的扩展,是除 extend、implements 外的另外一种扩展对象方式。

    Traits 既可以使单继承模式的语言获得多重继承的灵活,又可以避免多重继承带来的问题。

  • 相关阅读:
    P1001 A+B Problem
    NOIP2015D1T2 信息传递
    海淀区赛游记。。。。
    P3375 【模板】KMP字符串匹配
    Print Article HDU
    BZOJ-2-4870: [Shoi2017]组合数问题 矩阵优化 DP
    BZOJ-1- 4868: [Shoi2017]期末考试-三分
    #6164. 「美团 CodeM 初赛 Round A」数列互质-莫队
    湖南大学第十四届ACM程序设计新生杯(重现赛)
    Codeforces Round #530 (Div. 2)
  • 原文地址:https://www.cnblogs.com/niuben/p/10853767.html
Copyright © 2011-2022 走看看