美文网首页软件测试程序员
Selenium Web Driver自动化测试(java版)系

Selenium Web Driver自动化测试(java版)系

作者: 马可吃菠萝 | 来源:发表于2018-08-03 07:15 被阅读4次

    咱们介绍多态时最后讲了一个抽象类的概念,说父类如果不想空着方法体就可以用抽象方法,而有抽象方法的类就一定要被声明成抽象类。咱们也说了反过来却不一定,抽象类可以不包含抽象方法。有人就说了,好烦呐,明明抽象类,你还可以包含一般方法甚至不包含抽象方法,这不是挂羊头卖狗肉?就不能只包含抽象方法?于是一个比抽象类更抽象的东西产生了,也是我们在面向对象这个大范围内讲的最后一个概念 – 接口。

    接口和类比较类似,先说说它们的异同。首先,声明的格式很像,类是

    而接口是

    第二点,接口里面只有静态常量和抽象方法,没有变量。常量都是静态的,方法都是抽象的。而且在接口里静态常量不需要写static关键字,抽象方法也不用写abstract关键字。接口的成员方法只能包含抽象方法,不能像抽象类一样可以包含普通方法了。

    第三点,普通类可以被实例化,但接口不能。

    第四点,抽象类中方法被继承的类实现,接口中方法被实现接口的类实现。什么叫实现接口的类呢?我们知道,一个类被另一个类继承,格式是

    而一个接口是不能被继承的,只能被实现,格式是:

    实现接口用的关键字是implements。你看实现接口和继承类形式很像,其实原理也是差不多的,相通的。既然是相通的,那代表着最重要的还是要提取出相同的元素组成一个基础,只不过这里面基础不再是父类,而是接口了。

    第五点,子类继承父类时感觉就像把父类的方法复制粘贴过来,然后可以对方法进行重写;而类实现接口时也会拿到接口里的所有抽象方法(这点和继承差不多),但必须对每一个方法进行实现,除非该类是抽象类:

    对于抽象类来说,implements接口后也拿到了所有抽象方法,只不过不用实现罢了。那我们就演示一下,把多态、抽象方法、抽象类那篇文章中浏览器的例子改成用接口实现的。先把这个项目结合上篇所学复习一下,然后我们开始修改。新建一个项目叫BrowserInterface -> 添加包com.browsers -> 右键点击com.browsers包 -> New -> Interface,输入BrowserIF添加一个接口。第一步,和继承一样,先提取一样的元素。当时父类Browser.java是这么写的:

    父类Browser中的name,manufacturer和expectedResponseTime都被子类继承,它们都是相同元素。但可以把它们写到接口里吗?刚才说了,接口里的成员变量要满足两个条件,静态并且是final常量。这三个变量明显不能被写成常量,否则一会儿实现接口的时候还怎么显示三个不同浏览器的信息呢?所以,它们都不能写到接口里。但是,getActualResponseTime方法可以放到接口里,因为它是抽象方法。所以,我创建一个叫BrowserIF.java的接口文件,然后把getActualResponseTime方法写到里面去。另外,我实在是觉得给大家演示的时候应该尽量全面,接口里只有一个方法没有变量觉得实在不完整。这样,我稍稍改一下题目。还是测试打开某个网站时浏览器的响应时间,只不过需要把网络延时考虑进去。这个网络延时是个常量,比如1秒钟。Eclipse新建接口的方式也是用new:

    所以BrowserIF.java就变成了:

    浏览器名称、制造商、期望响应时间这三个成员变量因为不能写到接口里,所以依旧写到Browser.java类里:

    现在的项目结构如下:

    第二步,写三个浏览器的类。它们implements接口就可以得到getActualResponseTime方法并且实现:

    IE类:

    Chrome类:

    Firefox类:

    第三步,浏览器子类光拿了方法,别忘了还没拿那三个变量呢。那三个变量还在Browser类里,所以还得继承。你看,子类既要从BrowserIF中拿到成员方法,又要从Browser中拿到变量。java允许在实现接口的同时继承其它类。格式如下:

    注意,要先继承类再实现接口。之前讲继承说java不允许多继承,设计接口这个东西或许也是java为了弥补无法多继承而做出的一个折中办法吧。

    所以,我让这三个子类再继承Browser类:

    IE类:

    Chrome类:

    Firefox类:

    这一段代码既有类,又有接口,理解起来可能不是很容易。我们再重复一遍,因为子类既要从BrowserIF中拿到成员方法,又要从Browser中拿到成员变量,所以才要extends和implements同时使用。简单画张程序解析图:

    现在项目结构如下:

    第三步,写Test.java主类,基本上没什么改动,直接复制粘贴:

    还是父类对象初始化子类。我们发现b.getActualResponseTime()这句代码报错了,为什么呢?

    很简单,b虽然指向了子类,但父类里并没有getActualResponseTime这个方法。还记得多态、抽象方法、抽象类那篇怎么说的?实现多态时父类引用调用子类方法时必须保证该方法是继承来的,父类不能访问子类自己独有的。那怎么让父类也有这个方法呢?让父类也imeplements BrowserIF接口呗,这样不就拿到了么?而且刚才讨论类和接口对比时的最后一点也说了,对于抽象类来说,implements接口后也拿到了所有抽象方法,只不过不用实现罢了。父类Browser是抽象类,所以也没必要非得实现任何方法。我把Browser.java改一下:

    写完就不出错了。执行一下:

    我们的程序解析图就变成了这个样子:

    仔细看看解析图,我们发现父类Browser.java既有成员变量又有成员方法,已经全了。虽然方法是抽象的吧,但没关系。自己本身又是个抽象类。在多态、抽象方法、抽象类那篇里我们说当抽象类被继承时,里面所有的抽象方法都要被实现,那么子类IE/Chrome/Firefox继承时本来就要实现getActualResponseTime方法的。所以,子类还有必要implements接口吗?没必要呀。这块儿又有点乱,不过概念清楚就不会混淆。我把子类implements都拿掉:

    最后子类的程序如下:

    IE类:

    Chrome类:

    Firefox类:

    子类从一开始implements接口,到继承父类同时implements接口,再到最后只继承父类,我们转了一圈又回到了起点。以后大家就知道了,遇到类似的情况直接让父类实现接口就好,我也相信有人一开始就知道只要修改父类就行了,用不着兜这么大一个圈子。有人说完蛋了,我怎么知道什么时候用普通方法/静态方法/抽象方法/抽象类/普通类呢?这么多早弄混了。这就是我举浏览器这个例子的目的。其实很多时候写代码是慢慢试出来的,写多了自然就有感觉了,你就知道什么时候该用什么了,好多东西其实都有套路的。你看我修改这个程序的过程,其实就是看缺什么补什么,差什么改什么。其实这个程序肯定还能修改简化,但我不是大牛程序架构师,我目的很简单,就是看着输出结果想找到实现的方法。所以,咱们一开始不用纠结用什么方法最好,先实现了再说,只要能抓到耗子的猫都是好猫。实现了后,再看看哪儿可以改再慢慢改,比如我是不是应该用private而不是public啦,是不是用抽象方法比普通方法好呀,或是是不是应该把一个类继承改成一个接口实现更代码量更少等等。

    有人说如果项目里有多个接口呢?没问题,一个类可以实现多个接口,只要把所有接口的方法都实现就好,我就不演示了,它的格式是:

    到现在为止,咱们关于类方面的知识就暂时告一段落,我似乎听到了有人长长地吁了一口气,终于讲完了,赶紧讲完吧。其实面向对象博大精深,还有很多知识点没覆盖到,但现在的知识足以应付以后写自动化测试代码了,毕竟我们专注的是测试,不是开发,如果有兴趣的朋友可以自己去了解一下。我们介绍了类,学了成员方法,学了成员变量。方法里又有构造方法,静态方法,抽象方法等等很多概念,消化起来需要时间,没事多练练就有感觉了,还是那句话,都是套路。这篇文章的源代码是BrowserInterface项目,下篇介绍java数组。

    本篇知识点及注意事项:
    1. 接口里面只有静态常量和抽象方法,没有变量。常量都是静态的,方法都是抽象的。
    2. 普通类可以被初始化,但接口不能。
    3. 接口中方法被实现接口的类实现。
    4. 类实现接口时也会拿到接口里的所有抽象方法(这点和继承差不多),但必须对每一个方法进行实现,除非该类是抽象类。

    相关文章

      网友评论

        本文标题:Selenium Web Driver自动化测试(java版)系

        本文链接:https://www.haomeiwen.com/subject/qtgevftx.html