关键词:
规划程序之前要考虑到未来,及时做好应对需求变更的准备。
良好的面向对象程序设计需要尽量提高程序的扩展性和灵活性,当需求变更或加入新的类型时不至于重写设计或改写太多既有代码。众所周知,继承是面向对象程序设计三大基本特性(封装、继承、多态)之一,充分理解继承的原理机制,对于书写高质量的程序至关重要。
面向对象程序设计显著特点就是尽量少写重复代码,多考虑既有代码的重构,以此提高程序的扩展性。为什么需要继承机制?说白了就是为了减少重复代码。在设计继承时,我们总会从一系列具有相同属性和行为的类中抽象出共有的部分,然后封装在父类中,以Java方式来说,“子类继承父类”意味着子类拥有父类的实例变量和方法,这部分共有的属性和行为无需重新编写,直接继承即可;当然,子类也可以添加自己特有的实例变量和方法,利用继承机制可以大大程序设计的灵活性。
以上叙述了这么多,但好像太理论了,完全没有体现出继承的特点和优势。别着急,考虑这样一个案例:
“假设你需要设计一套动物仿真系统,可以使用户将一群动物丢至特定的环境,并因此模拟出不同动物的状态和行为。现已存在部分被告知的动物的属性和行为,但并不清楚以后会有多少动物被加进来。你需要设计扩展性良好的应用程序,以此应对后期动物园管理员以任意时间引进任意数量动物的需求。”
好吧,话有点啰嗦,还是直接开始设计吧。
(1)找出类间具有共同属性和行为的对象,并抽象出共有部分。
假设你的动物仿真系统需要存储动物的图像(picture)、食物(food)、饥饿程度(hunger)、活动范围的长和宽(boundaries)、活动过程中的X、Y坐标(location)、另外但凡动物均有发声(makeNoise)、饮食(eat)、睡眠(Sleep)、闲逛(roam)的行为。
假定现在的动物系统中有狮子(Lion)、老虎(Tiger)、猫咪(Cat)、河马(Hippo)、狼(Wolf)、狗(Dog)
(2)抽象出代表共同状态和行为的类
经以上分析我们抽象出动物(Animal)作为整个系统的顶层父类,并将共有的图像(picture)、食物(food)、饥饿程度(hunger)、活动范围的长和宽(boundaries)、活动过程中的X、Y坐标(location)实例变量和发声(makeNoise)、饮食(eat)、睡眠(Sleep)、闲逛(roam)方法加入Animal这个类中,并利用IDEA自动生成了Get和Set方法。
public class Animal { String picture;//动物图像的存储路径 String food;//目前只有meat和grass两种 Integer hunger;//饥饿程度 Double boundaries;//活动区域面积 Location location = new Location(); //活动坐标 public void makeNoise() {//发声 System.out.println("makeNoise method is invoked in Animal...."); } public void eat() { //饮食 System.out.println("eat method is invoked in Animal...."); } public void sleep() {//睡眠 System.out.println("sleep method is invoked in Animal...."); } public void roam() { //闲逛 System.out.println("roam method is invoked in Animal...."); } public String getPicture() { return picture; } public void setPicture(String picture) { this.picture = picture; } public String getFood() { return food; } public void setFood(String food) { this.food = food; } public Integer getHunger() { return hunger; } public void setHunger(Integer hunger) { this.hunger = hunger; } public Double getBoundaries() { return boundaries; } public void setBoundaries(Double boundaries) { this.boundaries = boundaries; } public Location getLocation() { return location; } public void setLocation(Location location) { this.location = location; } }
(3)确定子类是否需要重写方法和添加自己的实例变量
观察Animal,容易发现每个动物的eat()方法和makeNoise()方法的方式应该不一样,当然睡眠也可以不同,但为使得描述问题的简单,我们在此假定睡眠一样。以makeNoise()为例,狗狗(Dog)的发声是“汪汪汪”、猫咪(Cat)的发声是“喵喵喵”等等。。根据实际情况,每个子类都可以重写(overload)继承自父类的方法以满足自己的需求。例如Dog子类。
public class Dog extends Animal{ public void makeNoise() { System.out.println("大家好,我是旺财!,我喜欢旺旺旺..."); } public void eat() { System.out.println("大家好,我是旺财!,我喜欢鲜美的骨头..."); } }
当然其他的动物也可以根据自己的特性重写继承自父类的方法,或是添加实例变量,在此不再一一列出。
(4)寻找使用共同行为的子类来构造出更多的抽象化机会
现实世界中,动物本身具有组织化的层次(界、门、纲、目、科、属、种),据此,我们可以抽象出有意义的类。观察发现,现有动物中可以抽象出Canine(猫科)、Feline(犬科)两个科,其中狮子(Lion)、老虎(Tiger)、猫咪(Cat)属于Canine(猫科)、Hippo独立于猫科和犬科、狼(Wolf)、狗(Dog)属于Feline(犬科)。所以我们可以进一步的抽象出Canine和Feline两个类。
public class Canine extends Animal { public void roam() {//重写来自Animal的roam()方法 System.out.println("roam method is invoked in Canine...."); } }
public class Feline extends Animal { public void roam() { //重写来自Animal的roam()方法 System.out.println("roam method is invoked in Feline...."); } }
(5)完成类的继承层次
根据以上分析,我们可以完成类的继承层次,其中Animal属于顶层父类,Canine(猫科)、Hippo(河马)、Feline(犬科)分别继承自Animal;狮子(Lion)、老虎(Tiger)、猫咪(Cat)继承Canine(猫科);狼(Wolf)、狗(Dog)继承Feline(犬科),由此可得类间继承关系图
至此,动物仿真系统的所有类间关系就分析整理出来了,当然,每个子类可以任意添加自己的方法或是overload继承自父类的方法,极大的减少了重复代码的书写,并且提高了系统扩展性。
06继承与多态
继承与多态动手动脑问题:public class ParentChildTest{public static void main(String[]args){Parentparent=new Parent();parent.printValue();Childchild=new Child();child.printValue( 查看详情
继承与多态
1.请看以下“变态”的类publicclassParentChildTest{publicstaticvoidmain(String[]args){Parentparent=newParent();parent.printValue();Childchild=newChild();child.printValue();parent=child;parent.printValue();parent. 查看详情
学习-继承与多态
一继承 类与类的isa关系,叫做继承 关键字:extends-继承 语法:publicclass子类名extends父类名{ 效果:父类所以属性行为子类自动具有;java中只有单继承,一个子类只能继承一个父类 重写:子类把来自于父类的方法覆... 查看详情
继承与多态
1. 代码: publicclassTest{publicstaticvoidmain(Stringargs[]){Ca=newC();a.display();}}classA{publicvoiddisplay(){System.out.println("hello");}}classCextendsA{publicvoiddisplay(){System.out 查看详情
继承与多态
我们可以从某个现有的class继承定义一个class,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Baseclass、Superclass)如:classDog(Animal):而不是classDog(object):好处:1.子类能获得父类的全部功能,包括父类的方法2... 查看详情
继承与多态
1.继承中类型的转换源代码:classMammal{}classDogextendsMammal{}classCatextendsMammal{}publicclassTestCast{publicstaticvoidmain(Stringargs[]){Mammalm;Dogd=newDog();Catc=newCat();m=d;d=m;d=(Dog)m;d=c;c=(Cat)m;}}这个程序 查看详情
继承与多态-课后作业
1. 继承条件下的构造方法调用classGrandparent{publicGrandparent() { System.out.println("GrandParentCreated."); }publicGrandparent(Stringstring) { System.out.println("GrandParentCreated.String:"+string); }}cla 查看详情
继承与多态(代码片段)
第三章:继承与多态知识梳理面向对象具有三大特性:封装、继承、多态本章的内容:学习Java中包的概念以及另外两大特征:继承和多态。1.包的定义与使用(1)Java中通过包来完成对类的管理,每个... 查看详情
类的继承与多态
继承//概念:子类可以继承父类的一切//方法重写:在子类里面对父类的方法进行重写//特点:单继承:一个子类只能有一个父类,一个父类可以派生出多个子类//override:重写//overload:重载,编译多态classRen{ public$name; func... 查看详情
继承与多态(代码片段)
最近学习廖大的教程,看到类的继承与多态,看了一下做一下总结。 自雷继承父类的时候,可以继承父类里定义的函数(类里定义函数的时候一定要将第一个参数定义self,class后面紧接着是类名,即Student,类名通常是... 查看详情
第10章接口继承与多态
10.1packagetex;publicabstractclassone abstractvoidtest(); publicstaticvoidmain(Stringargs[]) newone(); //无法实例化 查看详情
继承与多态动手动脑
方法覆盖(override)”的要点classFather{publicvoidprintValue(){System.out.println("Parent.printValue()JmyValue");}}classSonextendsFather{ publicvoidprintValue(){ super.printValue();System.out.println("Child.pr 查看详情
06-继承与多态(动手动脑与验证)
一、继承条件下构造方法的调用测试代码一:1classGrandparent2{3publicGrandparent()4{5System.out.println("GrandParentCreated.");6}7publicGrandparent(Stringstring)8{9System.out.println("GrandParentCreated.String:"+string);10} 查看详情
继承与多态
1. 观察输出,注意总结父类与子类之间构造方法的调用关系修改Parent构造方法的代码,显式调用GrandParent的另一个构造函数,注意这句调用代码是否是第一句,影响重大!classGrandparent{publicGrandparent(){Syst... 查看详情
06-继承与多态
...;不能反过来,因为先有父类,再有子类,子类是从父类继承来的。packagedong;publicclassA{publicstaticvoidmain(String[]args){ //TODO自动生成的方法存根Childrenchildren=newChildren();children.Myname(); }packagedong;publicclassP 查看详情
继承与多态
...类型时不至于重写设计或改写太多既有代码。众所周知,继承是面向对象程序设计三大基本特性(封装、继承、多态)之一,充分理解继承的原理机制,对于书写高质量的程序至关重要。 面向对象程序设计显著特点就是尽量... 查看详情
多态与继承
多态:可对不同类型的对象执行相同的操作。继承:继承是一种另一种偷懒的方式,程序员总是想避免多次输入同样的代码。可以通过创建函数来达到这个目标,但现在要解决一个更微妙的问题。如果你已经有了一个类,并要创... 查看详情
继承与多态
1.构造函数:完成对象的初始化工作 以下代码为何无法通过编译?哪儿出错了? 编译器提示:构造函数Foo()未定义 //正确代码如下publicclassTest publicstaticvoidmain(String[]args) &... 查看详情