一些软件可复用性的学习心得

目录

一、什么是软件的可复用性

1.概念

2.复用的几个level

二、设计一个可复用的类

1.行为子类型与Liskov替换原则

2.Liskov替换原则

3.协变与逆变


一、什么是软件的可复用性

1.概念

软件的可复用性就是用现有的软件组件来更新软件的过程,它分为四个层面:

对应下来有两种编程的方式:面向复用编程和基于复用编程。前者就是为了能够去复用你正在编写的板块而有目的性地编程,后者就是利用现有的可复用模块去开发新功能。

2.复用的几个level

1.源代码级别的复用,最主要的复用就是代码层面的复用,任何实体都可能被复用:规约、代码、测试用例

2.模块级别的复用:类/抽象类/接口,对类的复用又可以分成继承和委托

3.库级别的复用:API/包

4.系统级别的复用:框架(Framwork 一组具体类、抽象类及其之间的连接关系)

二、设计一个可复用的类

1.行为子类型与Liskov替换原则

子类型多态:客户端可用统一的方式处理不同类型的对象

eg.若Cat是Animal的子类型,任何用Animal的场合都可以用Cat来替代

Animal a = new Animal();
Animal c1 = new Cat();
Animal c2 = new Cat();

//这么替换是没问题的
//a=c1;
//a=c2;

2.Liskov替换原则

我认为其中比较重要的有:

1.子类型中重写的方法必须有相同或者子类型的返回值,或符合co-variance的参数

2.子类型中重写的方法必须用同类型的参数或者符合contra-variance的参数

LSP对归约的应用:

子类型有同样或更强的不变量,同样或更弱的前置条件,同样或更强的后置条件

首先子类必须完全继承不变量,如下Car类必须继承speed<limit的不变量

abstract class Vehicle{
    int speed,limit;
    //@invariant speed < limit
    ...
            }

class Car extands Vehicle{
    int fuel;
    boolean engine;
    //@invariant speed < limit
    //@invariant (someother condision)
    ...
            }

其次子类中重写的方法规约不能弱于父类的方法

class Car extands Vehicle{
    int fuel;
    boolean engineOn;
    //@ invariant speed < limit;
    //@ invariant fuel >= 0;

    //@ requires fuel > 0 && !engineOn;
    //@ ensures engineOn;
    void start(){...}

    //@ requires speed != 0;
    //@ ensures speed < \old(speed)
    void brake(){...}
     }


class Hybrid extands Car{
    int charge;
    //@ invariant charge >= 0;

    //@ requires (charge > 0 || fuel > 0) && !engineOn;
    //@ ensures engineOn;
    void start(){...}

    //@ requires speed != 0;
    //@ ensures speed < \old(speed);
    //@ ensures charge > \old(charge)
    void brake(){...}
    }

可以看到Hybrid的start()方法的前置条件是弱于Car类start()方法的前置条件的,但Hybrid的brake()方法的后置条件是强于Car的brake()方法的。

3.协变与逆变

1.协变是从父类型到子类型越来越具体,返回值类型和异常的类型不变或者变具体

class T{
    Object a(){...}
}

class S extands T{
    @Override
    String a(){...}
}

2.逆变也叫反协变,子类型的参数越来越宽泛,目前Java遇到这种情况当作overload看待

class T {
    void c(String s) {...}
}

class S extands T {
    @Override
    void c(Object s ){...}
}

3.数组是协变的

Number [] numbers = new Number[2];
numbers[0] = new Integer (10);
numbers[1] = new Double (3.14);

因为Integer和Double都是Number的子类,所以直接把这些对象赋值给number类型是ok的,但是下面这种情况不行:

Number [] numbers ; //只有声明,没对象
Integer myInts = {1,2,3,4};
numbers = myInts; //现在numbers是一个Integer类型的数组,相当于这个数组指向了myInts数组
numbers[0] = 3.14 //run-time 报错

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值