首页 > 相学 > 面相

面对对象的基础「特性」

时间:2023-06-28 来源:m.86027.cn

1.封装

类是由数据(属性)和方法共同构成的。

封装是为了更好的规整里面的数据和方法,也能隐藏其中的数据和方法,通过控制不同的访问权限。来做好对外部的授权

比较现实的举例就是,我们用洗衣机或是开汽车,都是有这个产品提供的几个对外的模式和方法,而无需去了解里面过多的具体实现。

封装的好处,控制授权,易用,数据规整。这些都是相当于面向过程中的指令模式,大量的数据和方法从头贯穿。

举例更直观(PHP)

<?phpnnclass Promotionn{n private $total;n private $discount;n n //构造函数,初始化数据n function __construct($total, $discount)n {n $this ->total = $total;n $this ->discount = $discount;n }nn //获得需要抵扣的金额n public function getDiscountPirce()n {n return $this->discount;n }n }n

举例更直观(java)

class Promoiton{n protected double total;n protected int discount;n //构造函数,初始化数据n public Promoiton(double $total, int $discount){n this.total = $total;n this.discount = $discount;n }nn //运算对应的促销减去的金额n public double getDiscountPirce(){n return this.discount;n }n}

上述的代码中,我们定义了一个促销类,其中定义了两个数据(属性),分别是商品总价和折扣金额。以及一个获得抵扣金额的方法

uml举例

上述的uml类图中,从上到下,以此由类名、属性、方法组成。属性和方法前由对应的访问修饰符,用来控制不同关系中的访问权限。

2.抽象

抽象可以相对与封装来理解,抽象更多的是隐藏方法的实现细节。这个是我几年前,感觉最不好理解的东西,当时给我的感觉就是好抽象呀,哈哈。后来随着团队作用的不一样,才算慢慢对这个理解更深刻。

举一个例子,现在你接到一个需求,需要做一个员工内购的功能。我们不可能上来就进行编码。一定是先要解决问题的思路。比如先做需求的分析,拆解。一般拆到模块,比如会员模块的改造,商品模块的改造等等。具体在分析具体的某个模块,这个时候,可能就会想到怎么编码了,需要什么样的方法,怎么样的数据流转。其实定义类和对应的方法,这种就可以理解为抽象,是在更高的纬度来思考问题,当然在具体的语言中,可能就是个interface的关键字。先不说这样对设计模式的实现怎么样怎么样。最起码,你看抽象接口就知道大体的功能和逻辑,以后不管是需求变更还是扩展,都会非常的顺手。如果没有这层好的抽象,只能一行行的跟代码,理解业务,效率极低不说,未来有新成员进入团队,也很难上手

抽象的优点。更高层次的思考,才能让我们做更多的事情。读过人月神话的都知道,软件工程没有银弹,我们都是设法提高我们的效率。

抽象也是一种好的设计思想,很多的设计原则也都体现了抽象的设计思想。比如高聚合,低内聚、面相接口而非实现等。

3.继承

继承表示子类和父类,is-a的关系。当前常用的语言中,python是可以多继承的,php和java等都是单继承的逻辑

子类拥有父类的属性和方法。

可以减少不必要的代码量,既然可以继承,势必这些类直接的关系比较密切。香蕉这个类不会想着去继承飞机这个类。

一般继承分为2种,一种是继承普通类,一种是继承(接口实现)抽象类或是接口。

大多数语言类不能多继承,但是接口缺可以。

举例更直观(PHP)

<?phpnn//父类nclass Promotion{nn protected $total;n protected $discount;nn //构造函数n function __construct($total, $discount)n {n $this ->total = $total;n $this ->discount = $discount;n }nn public function getDiscountPirce()n {n return $this->discount;n }n}nn/**n* 满折n*/nclass FullDiscount extends promotionn{n protected $total;n protected $discount;nn //运行父类构造函数n function __construct($total, $discount)n {n parent::__construct($total, $discount);n }n n public function getDiscountPirce()n {n //TODOn }n}n

举例更直观(java)

//定义促销类(满减)nclass Promoiton{n protected double total;n protected int discount;nn public Promoiton(double $total, int $discount){n this.total = $total;n this.discount = $discount;n }nn //运算对应的促销减去的金额n public double getDiscountPirce(){n return this.discount;n }n}nn//定义满折(8折传过来的值为80即可)nclass FullDiscount extends Promoiton{n public FullDiscount(double $total, int $discount){n super($total, $discount);n }n}

上述为普通的类继承,普通继承和抽象类或接口类继承的最大区别是,不需要强制实现父类的方法。为啥有些需要强制实现,还是因为抽象类或接口中,一般不放具体的实现方法。只定义有那些功能。

uml举例(普通继承)(也是上述代码的uml体现)

上图为普通继承的逻辑,相关的说明也在图示备注中有体现

uml举例(抽象接口)

4.多态

多态是指,在实际的代码运行中,子类可以替换父类的方法做实现。

语言有动态语言和静态语言,所以多态实现也分为两类。继承加重写,duck-typing两种实现模式(动态语言)

多态也是实现很多设计模式的方式。后续到了具体的章节会有说明。

下方的案例,描述的业务场景,就是计算不同促销下,优惠的金额

举例更直观(php)(继承加重写)

<?phpnn//父类方法(计算满减金额)nclass Promotion{nn protected $total;n protected $discount;nn function __construct($total, $discount)n {n $this ->total = $total;n $this ->discount = $discount;n }n //计算满减的逻辑n public function getDiscountPirce()n {n return $this->discount;n }n}nn/**n* 满折n*/nclass FullDiscount extends promotionn{n function __construct($total, $discount)n {n parent::__construct($total, $discount);n }n //计算满折的逻辑n public function getDiscountPirce()n {n return ((100 - $this->discount) * $this->total) / 100;n } n}nn/**n* 积分抵扣n*/nclass IntegralDeduction extends promotionn{n function __construct($total, $discount)n {n parent::__construct($total, $discount);n }n //计算积分抵扣的逻辑n public function getDiscountPirce()n {n return $this->discount / 10;n }n}n//实例化促销类,并且计算不同类型的促销优惠n$arr = [n new Promotion(1000,30),n new FullDiscount(1000,80),n new IntegralDeduction(1000,100),n ];n//计算不同的促销的金额总和nforeach ($arr as $key => $obj) {n $payment += $obj->getDiscountPirce();n}necho $payment;n

举例更直观(java)(继承加重写)

class Main{n //入口函数n public static void main(String[] args) {n Promoiton[] promoitons = new Promoiton[]{n new Promoiton(1000,30),n new FullDiscount(1000, 80),n new IntegralDeduction(1000, 100),n };n System.out.println(getTotal(promoitons));n }nn //计算总共需要减去的金额n public static double getTotal(Promoiton... promoitons){n double payment = 0;n for (Promoiton promoiton : promoitons){n payment = payment + promoiton.getDiscountPirce();n }n return payment;n }nn}nn//定义促销类(满减)nclass Promoiton{n protected double total;n protected int discount;nn public Promoiton(double $total, int $discount){n this.total = $total;n this.discount = $discount;n }nn //运算对应的促销减去的金额n public double getDiscountPirce(){n return this.discount;n }n}nn//定义满折(8折传过来的值为80即可)nclass FullDiscount extends Promoiton{n public FullDiscount(double $total, int $discount){n super($total, $discount);n }nn //运算对应的折扣金额n public double getDiscountPirce(){n return ((100 - this.discount) * this.total)/100;n }n}nn//定义积分抵扣(积分比例为10:1)nclass IntegralDeduction extends Promoiton{n public IntegralDeduction(double $total, int $discount){n super($total, $discount);n }nn //运算对应的折扣金额n public double getDiscountPirce(){n return this.discount/10;n }n}

举例更直观(python)(duck-typing)

class English:n def record(self):n print("hello")nnclass Chinese:n def record(self):n print("你好")nndef test(recorder):n recorder.record()nndef demo():n english = English()n chinese = Chinese()n test(english)n test(chinese)nn#执行函数ndemo()n#输出对应的数据nhellon你好

通过上述的代码,加上之前的对于封装,继承,抽象的讲解。我想大家应该对于上述的多态,也有不错的了解。

其实核心就是方法重写。这个东西看似很简单,但是在不同的应用中,却又非比寻常的价值。后续我们会有更多的说明。

下篇见

上一篇:眉毛能改运吗?面相大师:别看我,我没说!

下一篇:隐藏在脸上的婚姻密码