关于抽象类和接口的初步理解

什么是抽象类

  1. 抽象类是指在 class 前加了 abstract 关键字且存在抽象方法(在类方法 function 关键字前加了 abstract 关键字)的类。

  2. 抽象类不能被直接实例化。抽象类中只定义(或部分实现)子类需要的方法。子类可以通过继承抽象类并通过实现抽象类中的所有抽象方法,使抽象类具体化。

  3. 如果子类需要实例化,前提是它实现了抽象类中的所有抽象方法。如果子类没有全部实现抽象类中的所有抽象方法,那么该子类也是一个抽象类,必须在 class 前面加上 abstract 关键字,并且不能被实例化。
    引用链接

  1. 接口(Interface)—— 定义行为

  2. 抽象类(Abstract Class) —— 实现行为

  3. 具体类(class)——执行行为
    引用链接

  1. 抽象类就是一个类的服务提供商,拥有众多服务,你不用必须用,当需要的时候你来用就可以,如果你觉得不提供服务不满意,你还可以自己来做。

  2. 抽象方法是必须实现的方法。就象动物都要呼吸。但是鱼用鳃呼吸,猪用肺呼吸。
    动物类要有呼吸方法。怎么呼吸就是子类的事了。

引用链接

为什么要使用抽象类

按照我目前的知识理解:

  1. 保持程序的一致性

  2. 抽象类限制了实现的方法,也是为了保持一致性

  3. 增加代码重用性,例如一些公共类不需要实现,只需要调用里面的方法就可以了。

  4. 现在有很多讨论和建议提倡用interface代替abstract类,两者从理论上可以做一般性的混用,但是在实际应用中,他们还是有一定区别的。抽象类一般作为公共的父类为子类的扩展提供基础,这里的扩展包括了属性上和行为上的。而接口一般来说不考虑属性,只考虑方法,使得子类可以自由的填补或者扩展接口所定义的方法,就像JAVA王子所说的事件中的适配器就是一个很好的应用。

用一个简单的例子,比如说一个教师,我们把它作为一个抽象类,有自己的属性,比如说年龄,教育程度,教师编号等等,而教师也是分很多种类的,我们就可以继承教师类而扩展特有的种类属性,而普遍属性已经直接继承了下来。

而接口呢~还是拿教师做例子,教师的行为很多,除了和普通人相同的以外,还有职业相关的行为,比如改考卷,讲课等等,我们把这些行为定义成无body的方 法,作为一个集合,它是一个interface。而教师张三李四的各自行为特点又有不同,那么他们就可以扩展自己的行为body。从这点意义上来说,interface偏重于行为。

引用链接

怎样使用抽象类

<?php
    abstract class  Shape{  //这是一个抽象类,不能实例化
        protected  $color;  //抽象类里面一般都是使用protected来保护属性,这是封装的意义
        
        public function __construct($color = 'red') {   //抽象类可以使用构造方法,主要是为了方便代码重用,构造方法里面也可以使用默认参数,当没有配置参数的时候,就会使用默认的参数,写法如上
            $this->color = $color;
        }
        
        public function getColor() {  //只是为了演示需要的一个方法
            return $this->color;
        }
        
        abstract public function getArea();  //构造方法是为了限制代码,对于继承这个构造类的子类,必须限制拥有这个构造方法,主要为了保持代码一致性。
    }
    
    class Square extends Shape{
        protected  $length = 4;
        public function getArea() {
            return pow($this->$length, 2);
        }
    }
    
    class Circle extends Shape{ //这里因为没有构造方法getArea,所以代码允许会报错的。
        
    }
    
    $shape = new Square();
    var_dump($shape);
?>

接口和抽象类

  1. 抽象类不能被直接实例化,抽象类中只定义子类需要的方法,子类可以继承并且通过实现其中的抽象方法,使抽象类具体化。例如一个名为media的类,他是用于描述各种公开出版的共同性质,因为media不表示真实的实体,而是一些相似实体的泛化表示,所以不实例化,这样就需要声明为抽象类,然后再由各种的派生的Media类继承此抽象类

  2. 抽象类的每个子类都必须实现抽象类中的所有抽象方法,或者把他们自身也声明为抽象方法。

  3. 扩展类不仅仅负责简单实现抽象类的方法,还必须重新声明方法,新的方法不能比抽象方法的访问控制更严格,新的实现方法的参数个数应该和抽象方法的参数个数一样。

  4. 接口定义了实现某种服务的一般规范,声明了必须的函数和常量,但是不指定如何实现。关键是要建立必须实现的一组一般原则,只有满足了这些原则才能说实现了这个接口。

  5. 抽象类提供了具体实现的标准,而接口则是纯粹的模板。接口只能定义功能而不包含实现的内容。

  6. 任何实现接口的类都要实现接口中所定义的所有方法,否则类必须声明为abstract。

  7. 实现接口的类接受他的继承的类以及实现的接口的类型。

什么时候用接口,什么时候用抽象类

  • 如果要创建一个模型,这个模型将由一些紧密相关的对象引用,就可以采用抽象类,如果要创建将由一些不想关的对象采用的功能,应该用接口。

  • 如果必须从多个来源继承行为,就是用接口。

  • 如果知道所有类都会共享一个公共的行为实现,就使用抽象类,并在其中实现行为。接口无法实现。

  • 一个类只能extends一个父类,但可以贯彻多个接口。

接口作用一:

接口类就是一个类的领导者,指明方向,子类必须完成它指定方法。

当有很多人一起开发一个项目时,可能都会去调用别人写的一些类,那你就会问,我怎么知道他的某个功能的实现方法是怎么命名的呢,这个时候php接口类就起到作用了,当我们定义了一个接口类时,它里面的方式是下面的子类必须实现的,比如

interface Shop
{
public function buy($gid);
public function sell($gid);
public function view($gid);
}

class BaseShop implements Shop
{
    public function buy($gid)
    {
        echo '你购买了ID为 :' . $gid . '的商品';
    }

    public function sell($gid)
    {
        echo '你购卖ID为 :' . $gid . '的商品';
    }

    public function view($gid)
    {
        echo '你浏览了ID为 :' . $gid . '的商品';
    }
}

接口作用二:

有时候,我们需要设计一个物品,比如shape,这个shape有不同的形状,有不同的颜色,可作不同的运动,等等。当然我们可以把这些都放在一个类里面,但这样,如前面说的,只是过程编程,不是OO编程。你会说,像上面例子一样,做一个抽象类,然后在子类里实现所有的功能。好象不错,进步了。这样子类里面要实现形状,颜色,运动等功能,OK吗?记住,OO里面还有一条原则,为了最大程度的做到代码重用,一个类里最好只实现一个功能,也就是说,一个类做形状,一个类做颜色,一个类做运动 。这样如果其他的类要用到颜色的功能时,我们就可以重用这个颜色类,同理,这样我们可以很容易的重用运动类,形状类,等等。

但这样问题出来了,现在我们要用到上面所有的功能,但又分散在三个类里面,怎么办?这时我们就要用到抽象类和接口了。选定一个跟shape关联最大的一项–形状,把它做成抽象类, 其他两样,把它们做成接口,然后在子类里面extends一个抽象类,再implements两个接口就行了。如:

class Square extends Shape implements 颜色, 运动, ... {
...
}

抽象类作用一:

抽象类就是一个类的服务提供商,拥有众多服务,你不用必须用,当需要的时候你来用就可以,如果你觉得不提供服务不满意,你还可以自己来做。

这里是一个例子,想上面一样我定义了一个商店类,抽所了它所有像的部分,买(buy),卖(sell),看(view),并且抽象类里都实现了这些方法,那么继承它的子类就自动获得了这些方法,子类就做它自己独特的东西,减少代码的重复,提高复用性。

abstract class BaseShop
{
    public function buy($gid)
    {
        echo '你购买了ID为 :' . $gid . '的商品';
    }

    public function sell($gid)
    {
        echo '你购卖ID为 :' . $gid . '的商品';
    }

    public function view($gid)
    {
        echo '你浏览了ID为 :' . $gid . '的商品';
    }
}

class BallShop extends BaseShop
{
    var $itme_id = null;

    public function __construct()
    {
        $this->itme_id = 2314;
    }

    public function open()
    {
        $this->sell($this->itme_id);
    }
}

抽象类作用二:

在抽象类里面设置抽象方法

在oo设计时,会把一些通用的方法放在一个类里,但考虑到子类继承时的差异性,又不能把它事先实现,就只好用到这个抽象类或接口了。这里很清楚的显示了在抽象类里,我们贯彻了设原用到点setCenter()的方法,这样,当子类继承它时,就不用再重复写这个设原点的方法了。那么为什么draw的方法要设定成抽象方法呢?这是因为不同的子类要用不同的实现方法。

abstract class Shape
{
    function setCenter($x, $y)
    {
        $this->x = $x;
        $this->y = $y;
    }

    abstract function draw();

    protected $x, $y;
}

参考:http://chengxudaren.com/index.php?act=article&op=detail&a_id=152


线上猛如虎
2.2k 声望178 粉丝

你们都有梦想的,是吧.怀抱着梦想并且正朝着梦想努力的人,寻找着梦想的人,我想为这些人加油呐喊!