好看的网站在哪里好找,自己怎么个人网站,万网建设网站的步骤,网站搭建好后被移动宽带屏蔽怎么办7.1 民法亲属篇#xff1a;继承#xff08;inheritance#xff09;
了解继承
在设计继承时#xff0c;你会把共同的程序代码放在某个类中#xff0c;然后告诉其他的类说此类是它们的父类。当某个类继承另一个类的时候#xff0c;也就是子类继承自父类。以Java的方式说继承inheritance
了解继承
在设计继承时你会把共同的程序代码放在某个类中然后告诉其他的类说此类是它们的父类。当某个类继承另一个类的时候也就是子类继承自父类。以Java的方式说这是“子类继承父类”。继承的关系意味着子类继承了父类的方法。当我们提及“类的成员”时成员的意思就是实例变量和方法。
举例来说如果PantherMan是个SuperHero的子类则PantherMan会自动地继承SuperHero的实例变量和方法包括了suit、tights、specialPower、useSpecialPower()等。但PantherMan可以加入自己的方法和实例变量也可以覆盖掉继承自SuperHero的方法。 FriedEggMan不需要任何独特的行为所以它没有覆盖过任何的方法。
然而PantherMan认为它的特殊超能力需要特别处理过的方法所以就覆盖掉useSpecialPower()与putOnSuitO。
实例变量无法被覆盖掉是因为不需要它们并没有定义特殊的行为。PantherMan可以将继承下来的tights设定成紫色而FriedEggMan可以自行选择白色。
继承的范例
public class Doctor {boolean worksAtHospital;void treatPatient() {//执行检查}
}
public class FamilyDoctor extends Doctor{boolean makesHouseCalls;void giveAdvice() {//提出诊断}
}public class Surgeon extends Doctor{void treatPatient() {//进行手术}void makeIncision() {//截肢好恶心}
} 7.2 设计继承层次
设计动物仿真程序的继承树
假设你要设计一个仿真系统程序可以让用户设定将一群动物丢到某种环境中以观察会发生什么事情。现在不需要写出程序我们只在乎设计。
我们已经被告知一部分会用到的动物但是并不知道还有多少种动物会加进来。每个动物都会用一个对象来表示且动物会在环境中活动执行任何被设计出的行为。
这个程序必须能够在任何时间加入新类型的动物。
我们首先要辨别出所有动物都有的、抽象的共同特征然后以这些共同特征设计出能够让所有动物加以扩充的类。1.找出具有共同属性和行为的对象
这6种动物有什么共同点这么文可以帮助我们执行第二个步骤。这些类型有什么相关性这么问有助于这些第四到第五个步骤 7.3 运用继承避免重复的程序代码
运用继承来防止子类中出现重复的程序代码
我们有5个实例变量 picture动物JPEG图像的名称。
food此动物所吃的食物。现在只有meat和grass两种值。
hunger:代表饥饿程度的int值。它会根据动物吃了多少东西而改变。
boundaries代表动物活动范围区域的长宽。
location动物在活动区域中的X与Y坐标。
还有4个方法 makeNoise()动物发出声音的行为程序。 eat()动物遇到食物时的行为程序。 sleep()睡眠的行为程序。 roam()不在进食或睡眠时的行为程序。
2.设计代表共同状态与行为的类
这些对象都是动物因此可以用Animal作为共同父类的名称
会把所有动物都需要的方法和实例变量加进去 7.4 方法的覆盖override
假设我们都同意一件事所有Animal类型上的实例变量都合用。狮子的picture带有它的图片路径food的值是meat。猫的图片就是猫、猫的食物是meat(其实有养猫的人都知道猫也会吃草)。所以实例变量没有问题但是行为程序呢
我们应该覆盖哪些方法呢
狮子的叫声会跟河马一样吗也许你认为一样但是我们会根据类型设计出不同的行为程序。当然我们也可以用实例变量来存放声音文件的路径值而让makeNoise()方法都执行相同的动作。但是有时候行为的复杂程度不只是如此而已。
因此就跟阿米巴虫覆盖过rotate()这个方法的例子一样我们会让某些行为使用各个类自行指定的程序而不是使用共同的程序。
3.决定子类是否需要让某项行为也就是方法的实现有特定不同的运作方式
观察Animal这个类之后认为eat()与makeNoise()应该由各个子类自行覆盖 4.通过寻找使用共同行为的子类来找出更多抽象化的机会
观察到Wolf与Dog可以由某些共同的行为在Lion、Tiger、Cat之间也是 5.完成类的继承层次
因为动物本来就有组织化的层次界、门、纲、目、科、属、种我们可以用这些层次来制作有意义的类设计。我们使用犬科和猫科动物的分类来作出Feline与Canine这两个类。
我们决定Canine使用共同的roam()方法因为它们都以相同的方式移动。Feline之间也是差不多。而Hippo则持续使用继承下来的roam()方法。
所以这个层次就这么完成了稍后我们会再回到这个部分。 调用哪个方法 Wolf这个类有4个方法。其中一个继承自Animal一个来自Canine实际上也是覆盖过Animal的方法还有两个是自己覆盖过的。当你创建出一个Wolf对象并赋给它变量时你可以使用圆点运算符来调用变量所引用对象的方法。但是这会调用哪个版本的方法呢 当你调用对象引用的方法时你会调用到与该对象类型最接近的方法。换句话说最低阶的会胜出“最低阶”的意思是在层次树的最下方。Canine比Animal低而Wolf是在Canine的下方因此Java虚拟机会从Wolf开始找起。如果Java虚拟机找不到Wolf版的方法它会往上寻找直到找到为止。
7.5 美人出浴图
“是一个”与“有一个”
当一个类继承自另外一个类时我们会说这是子类去继承父类。若你想要知道某物是否应该要继承另一物时则可以用IS-A测试来检验。 三角形是一个多边型……嗯没错。 外科医生是一个医生……OK。 哈啰凯蒂是一个猫……算是吧。 澡盆是一个浴室……失败 大肠没有洗干净...…失败中的失败 要确认你的设计是否正确使用这样的测试来加以检验。如果不合理表示你的设计有问题。 浴室与澡盆确实有关联但不是继承上的关系。浴室与澡盆发生的是HAS-A的关系。如果“浴室有一个澡盆”成立的话这表示浴室带有澡盆的实例变量。也就是说浴室会有个澡盆的引用但是浴室并没有继承过澡盆。 等一下还有
IS-A测试适用在继承层次的任何地方。如果你的继承层次树设计得很好那么所有的子类都应该通过任一个上层父类的IS-A测试。如果类Y是继承类X且类Y是类Z的父类那么Z应该能通过IS-A X的测试。 就像此处所显示出的继承树你一定可以说“Wolf继承Animal”或“Wolf IS-A Animal”。只要Animal位于Wolf之上Wolf IS-AAnimal就一定会成立。 这张Animal继承图说明了 “Wolf是一个Canine因此Canine能做的事情Wolf都能做而Wolf也是个Animal所以Animal能做的事情Wolf也都能做”。 就算Wolf已经覆盖掉某些来自Animal或Canine的方法也一样。对其他的程序来说它们只要知道Wolf能够执行这4个方法就行。至于它是怎么做的或者它是覆盖过哪个类的则一点都不重要。至少有一件事情可以确定Wolf一定可以makeNoise()、eat()、sleep()和roam()。
如何知道继承设计是对的
虽然如此我们还是要提出IS-A测试这个建议。如果“X IS-A Y”合理则这两者或许存在于同 一个继承结构下。也有可能两者根本是相同的或者刚好有相同的行为。 注意继承概念下的IS-A是个单向的关系 “三角形是一个多边形”这是合理的所以你可以从多边形中扩充出三角形。 但是反过来说“多边形是一个三角形”并不合理所以多边形并不是从三角形中extend出来的。要记得X IS-A Y隐喻着X可以做出任何Y可以做的事情且还可能会做出更多的行为。
7.6 民法亲属篇遗产
子类可以继承父类的成员包括实例变量和方法。父类可以通过存取权限决定子类是否能够继承某些特定的成员。
本书中会讨论4中存取权限左边是最受限制的而越往右边限制程度越小 存取权限access level控制了谁可以接触什么这对编写出坚固、设计良好的Java程序来说是很重要的。现在我们先看看public与private两项
public类型的成员会被继承private类型的成员不会被继承
当子类把成员继承下来时会把它们当作是自己定义的一样。例如说当某个形状体继承Shape时就会有rotate()与playSound()这两个方法。 任一类的成员包含有自己定义出的变量和方法再加上从父类所继承下来的任何东西。 当某个类会比其父类更具有特定意义时使用继承。例如说美国短毛猫是一种特定品种的猫所以从猫中扩充出美国短毛猫是很合理的。在行为程序实现程序代码应该被多个相同基本类型类所共享时应该要考虑使用继承。举例来说方形、圆形、三角形都需要旋转和播放声音因此将这些功能放在它们的父类上面是很合理的并且这样也比较好维护和扩充。然而要注意到虽然继承是面向对象程序设计的一项关键特征但却不一定是达成重用行为程序的最佳方式。我们会教你如何运用继承这通常也是不错的选择但有时常用的“设计模式(design pattern)”也会提出更微妙且更有适应性的选择。若两者间的关系对于继承结构来说并不合理则不要只是因为打算要重用其他类的程序代码而运用继承。例如在设计钢琴对象时不能因为想要借用河马对象的发声程序就让这两个八竿子打不着的对象产生继承上的关系。这完全不合理应该要创建出发音对象然后让钢琴与河马都用HAS-A关系来运用此对象才对。如果两者间不能通过IS-A测试就不要应用继承关系。一定要确定子类是父类一种更特定的类型才可以。
7.7 继承的好处
1.避免了重复的程序代码
在单一的位置定义共同程序代码然后让子类继承父类的程序代码。当你想要改变这个行为程序时只需修改这个地方而子类就会发生同样的改变
2.定义出共同的协议
继承让你可以确保某个父类之下的所有类都会有父型所持有的全部方法全部可继承的方法public类型的方法通过继承来定义相关类间的共同协议
7.8 多态polymorphism
当你定义出一组类的父型时你可以用子型的任何类来填补任何需要或期待父型的位置
在多态下引用和对象可以是不同的类型
Animal myDog new Dog(); 运用多态时引用类型可以是实际大小类型的父类
当你声明一个引用变量时任何对该引用变量类型可通过IS-A测试的对象都可以被赋值给该引用。换句话说任何extends过声明引用变量类型的对象都可以被赋值给这个引用变量。这样子你就可以做出多态数组这一类的东西。 参数和返回类型也可以多态
声明一个父类的引用变量可以将子类对象赋给它 7.9 覆盖的规则
方法就是合约的标志
参数必须要一样且返回类型必须要兼容
父类的合约定义出其他的程序代码要如何来使用方法。不管父类使用了哪种参数覆盖此方法的子类也一定要使用相同的参数。而不论父类声明的返回类型是什么子类必须要声明返回一样的类型或该类型的子类。要记得子类对象得保证能够执行父类的一切。 不能降低方法的权限
这代表存取权必须相同或者更为开放。举例来说你不能覆盖掉一个公有的方法并将它标记为私有。这会让它以为在编译期通过的是个公有然后突然在执行期才被Java虚拟机阻止存取。目前为止我们看过了private与public这两种存取权限。 7.10 重载overload
方法的重载
重载的意义是两个方法的名称相同但参数不同。所以重载与多态毫无关系。
重载可以有同一方法的多个不同参数版本以方便调用。比如如果某个方法需要int调用方就得将 double转换成int然后才能调用。若你有个重载版本取用double参数则这样对调用方来说就简单多了。
因为重载方法不是用来满足定义在父类的多态合约所以重载的方法比较有扩展性。
返回类型可以不同
可以任意地改变重载方法的返回类型只要所有的覆盖使用不同的参数即可
不能只改变返回类型
如果只有返回类型不同但参数一样这是不允许的。编译器不会让这样的事情过关。就算是重载也要让返回类型是父类版返回类型的子类。重载的条件是要使用不同的参数此时返回类型可以自由地定义。
可以更改存取权限
可以任意地设定overload版method的存取权限。
重载版的方法只是刚好由相同名字的不同方法与继承或多态无关。重载的方法与覆盖方法不一样
重载的合法案例
public class Overloads {String uniqueID;public int addNums(int a, int b) {return a b;}public double addNums(double a, double b) {return a b;}public void setUniqueID(String theID) {//lots of validation code, and then:uniqueID theID;}public void setUniqueID(int ssNumber) {String numString ssNumber;setUniqueID(numString);}
}