当前位置: 首页 > news >正文

网站建设前端和后端酷站网官网

网站建设前端和后端,酷站网官网,泰安网站建设哪里有,wordpress编辑器知乎本章概要 结合组合和继承 保证适当的清理名称隐藏 组合与继承的选择protected向上转型 再论组合和继承 结合组合与继承 你将经常同时使用组合和继承。下面的例子展示了使用继承和组合创建类#xff0c;以及必要的构造函数初始化: class Plate {Plate(int i) {System.out.…本章概要 结合组合和继承 保证适当的清理名称隐藏 组合与继承的选择protected向上转型 再论组合和继承 结合组合与继承 你将经常同时使用组合和继承。下面的例子展示了使用继承和组合创建类以及必要的构造函数初始化: class Plate {Plate(int i) {System.out.println(Plate constructor);} }class DinnerPlate extends Plate {DinnerPlate(int i) {super(i);System.out.println(DinnerPlate constructor);} }class Utensil {Utensil(int i) {System.out.println(Utensil constructor);} }class Spoon extends Utensil {Spoon(int i) {super(i);System.out.println(Spoon constructor);} }class Fork extends Utensil {Fork(int i) {super(i);System.out.println(Fork constructor);} }class Knife extends Utensil {Knife(int i) {super(i);System.out.println(Knife constructor);} }// A cultural way of doing something: class Custom {Custom(int i) {System.out.println(Custom constructor);} }public class PlaceSetting extends Custom {private Spoon sp;private Fork frk;private Knife kn;private DinnerPlate pl;public PlaceSetting(int i) {super(i 1);sp new Spoon(i 2);frk new Fork(i 3);kn new Knife(i 4);pl new DinnerPlate(i 5);System.out.println(PlaceSetting constructor);}public static void main(String[] args) {PlaceSetting x new PlaceSetting(9);} }尽管编译器强制你初始化基类并要求你在构造函数的开头就初始化基类但它并不监视你以确保你初始化了成员对象。注意类是如何干净地分离的。你甚至不需要方法重用代码的源代码。你最多只导入一个包。(这对于继承和组合都是正确的。) 保证适当的清理 Java 没有 C 中析构函数的概念析构函数是在对象被销毁时自动调用的方法。原因可能是在 Java 中通常是忘掉而不是销毁对象从而允许垃圾收集器根据需要回收内存。通常这是可以的但是有时你的类可能在其生命周期中执行一些需要清理的活动。初始化和清理章节提到你无法知道垃圾收集器何时会被调用甚至它是否会被调用。因此如果你想为类清理一些东西必须显式地编写一个特殊的方法来完成它并确保客户端程序员知道他们必须调用这个方法。最重要的是——正如在异常章节中描述的——你必须通过在 **finally **子句中放置此类清理来防止异常。 请考虑一个在屏幕上绘制图片的计算机辅助设计系统的例子: class Shape {Shape(int i) {System.out.println(Shape constructor);}void dispose() {System.out.println(Shape dispose);} }class Circle extends Shape {Circle(int i) {super(i);System.out.println(Drawing Circle);}Overridevoid dispose() {System.out.println(Erasing Circle);super.dispose();} }class Triangle extends Shape {Triangle(int i) {super(i);System.out.println(Drawing Triangle);}Overridevoid dispose() {System.out.println(Erasing Triangle);super.dispose();} }class Line extends Shape {private int start, end;Line(int start, int end) {super(start);this.start start;this.end end;System.out.println(Drawing Line: start , end);}Overridevoid dispose() {System.out.println(Erasing Line: start , end);super.dispose();} }public class CADSystem extends Shape {private Circle c;private Triangle t;private Line[] lines new Line[3];public CADSystem(int i) {super(i 1);for (int j 0; j lines.length; j)lines[j] new Line(j, j * j);c new Circle(1);t new Triangle(1);System.out.println(Combined constructor);}Overridepublic void dispose() {System.out.println(CADSystem.dispose());// The order of cleanup is the reverse// of the order of initialization:t.dispose();c.dispose();for (int i lines.length - 1; i 0; i--) {lines[i].dispose();}super.dispose();}public static void main(String[] args) {CADSystem x new CADSystem(47);try {// Code and exception handling...} finally {x.dispose();}} }这个系统中的所有东西都是某种 Shape (它本身是一种 Object因为它是从根类隐式继承的) 。除了使用 super 调用该方法的基类版本外每个类还覆盖 dispose() 方法。特定的 Shape 类——Circle、Triangle 和 Line都有 “draw” 构造函数尽管在对象的生命周期中调用的任何方法都可以负责做一些需要清理的事情。每个类都有自己的 dispose() 方法来将非内存的内容恢复到对象存在之前的状态。 在 main() 中有两个关键字是你以前没有见过的在异常一章之前不会详细解释: try 和 finally。try 关键字表示后面的块 (用花括号分隔 )是一个受保护的区域这意味着它得到了特殊处理。其中一个特殊处理是无论 try 块如何退出在这个保护区域之后的 finally 子句中的代码总是被执行。(通过异常处理可以用许多不同寻常的方式留下 try 块。)这里finally 子句的意思是“无论发生什么始终调用 x.dispose()。” 在清理方法 (在本例中是 dispose() ) 中还必须注意基类和成员对象清理方法的调用顺序以防一个子对象依赖于另一个子对象。首先按与创建的相反顺序执行特定于类的所有清理工作。(一般来说这要求基类元素仍然是可访问的。) 然后调用基类清理方法如这所示。 在很多情况下清理问题不是问题你只需要让垃圾收集器来完成这项工作。但是当你必须执行显式清理时就需要多做努力更加细心因为在垃圾收集方面没有什么可以依赖的。可能永远不会调用垃圾收集器。如果调用它可以按照它想要的任何顺序回收对象。除了内存回收外你不能依赖垃圾收集来做任何事情。如果希望进行清理可以使用自己的清理方法不要使用 finalize()。 名称隐藏 如果 Java 基类的方法名多次重载则在派生类中重新定义该方法名不会隐藏任何基类版本。不管方法是在这个级别定义的还是在基类中定义的重载都会起作用: class Homer {char doh(char c) {System.out.println(doh(char));return d;}float doh(float f) {System.out.println(doh(float));return 1.0f;} }class Milhouse { }class Bart extends Homer {void doh(Milhouse m) {System.out.println(doh(Milhouse));} }public class Hide {public static void main(String[] args) {Bart b new Bart();b.doh(1);b.doh(x);b.doh(1.0f);b.doh(new Milhouse());} }Homer 的所有重载方法在 Bart 中都是可用的尽管 Bart 引入了一种新的重载方法。正如你将在下一章中看到的那样比起重载更常见的是覆盖同名方法使用与基类中完全相同的方法签名和返回类型。否则会让人感到困惑。 你已经看到了Java 5 **Override **注解它不是关键字但是可以像使用关键字一样使用它。当你打算重写一个方法时你可以选择添加这个注解如果你不小心用了重载而不是重写编译器会产生一个错误消息: // reuse/Lisa.java // (c)2017 MindView LLC: see Copyright.txt // We make no guarantees that this code is fit for any purpose. // Visit http://OnJava8.com for more book information. // {WillNotCompile}class Lisa extends Homer {Override void doh(Milhouse m) {System.out.println(doh(Milhouse));} }{WillNotCompile} 标记将该文件排除在本书的 Gradle 构建之外但是如果你手工编译它你将看到:method does not override a method from its superclass.方法不会重写超类中的方法 **Override ** 注解能防止你意外地重载。 组合与继承的选择 组合和继承都允许在新类中放置子对象组合是显式的而继承是隐式的。你或许想知道这二者之间的区别以及怎样在二者间做选择。 当你想在新类中包含一个已有类的功能时使用组合而非继承。也就是说在新类中嵌入一个对象通常是私有的以实现其功能。新类的使用者看到的是你所定义的新类的接口而非嵌入对象的接口。 有时让类的用户直接访问到新类中的组合成分是有意义的。只需将成员对象声明为 public 即可可以把这当作“半委托”的一种。成员对象隐藏了具体实现所以这是安全的。当用户知道你正在组装一组部件时会使得接口更加容易理解。下面的 car 对象是个很好的例子 // reuse/Car.java // Composition with public objects class Engine {public void start() {}public void rev() {}public void stop() {} }class Wheel {public void inflate(int psi) {} }class Window {public void rollup() {}public void rolldown() {} }class Door {public Window window new Window();public void open() {}public void close() {} }public class Car {public Engine engine new Engine();public Wheel[] wheel new Wheel[4];public Door left new Door(), right new Door(); // 2-doorpublic Car() {for (int i 0; i 4; i) {wheel[i] new Wheel();}}public static void main(String[] args) {Car car new Car();car.left.window.rollup();car.wheel[0].inflate(72);} }因为在这个例子中 car 的组合也是问题分析的一部分不是底层设计的部分所以声明成员为 public 有助于客户端程序员理解如何使用类且降低了类创建者面临的代码复杂度。但是记住这是一个特例。通常来说属性还是应该声明为 private。 当使用继承时使用一个现有类并开发出它的新版本。通常这意味着使用一个通用类并为了某个特殊需求将其特殊化。稍微思考下你就会发现用一个交通工具对象来组成一部车是毫无意义的——车不包含交通工具它就是交通工具。这种“是一个”的关系是用继承来表达的而“有一个“的关系则用组合来表达。 protected 即然已经接触到继承关键字 protected 就变得有意义了。在理想世界中仅靠关键字 private 就足够了。在实际项目中却经常想把一个事物尽量对外界隐藏而允许派生类的成员访问。 关键字 protected 就起这个作用。它表示“就类的用户而言这是 private 的。但对于任何继承它的子类或在同一包中的类它是可访问的。”protected 也提供了包访问权限 尽管可以创建 protected 属性但是最好的方式是将属性声明为 private 以一直保留更改底层实现的权利。然后通过 protected 控制类的继承者的访问权限。 // reuse/Orc.java // The protected keyword class Villain {private String name;protected void set(String nm) {name nm;}Villain(String name) {this.name name;}Overridepublic String toString() {return Im a Villain and my name is name;} }public class Orc extends Villain {private int orcNumber;public Orc(String name, int orcNumber) {super(name);this.orcNumber orcNumber;}public void change(String name, int orcNumber) {set(name); // Available because its protectedthis.orcNumber orcNumber;}Overridepublic String toString() {return Orc orcNumber : super.toString();}public static void main(String[] args) {Orc orc new Orc(Limburger, 12);System.out.println(orc);orc.change(Bob, 19);System.out.println(orc);} }输出 Orc 12: Im a Villain and my name is Limburger Orc 19: Im a Villain and my name is Bobchange() 方法可以访问 set() 方法因为 set() 方法是 protected。注意到类 Orc 的 toString() 方法也使用了基类的版本。 向上转型 继承最重要的方面不是为新类提供方法。它是新类与基类的一种关系。简而言之这种关系可以表述为“新类是已有类的一种类型”。 这种描述并非是解释继承的一种花哨方式这是直接由语言支持的。例如假设有一个基类 Instrument 代表音乐乐器和一个派生类 Wind。 因为继承保证了基类的所有方法在派生类中也是可用的所以任意发送给该基类的消息也能发送给派生类。如果 Instrument 有一个 play() 方法那么 Wind 也有该方法。这意味着你可以准确地说 Wind 对象也是一种类型的 Instrument。下面例子展示了编译器是如何支持这一概念的 // reuse/Wind.java // Inheritance upcasting class Instrument {public void play() {}static void tune(Instrument i) {// ...i.play();} }// Wind objects are instruments // because they have the same interface: public class Wind extends Instrument {public static void main(String[] args) {Wind flute new Wind();Instrument.tune(flute); // Upcasting} }tune() 方法接受了一个 Instrument 类型的引用。但是在 Wind 的 main() 方法里tune() 方法却传入了一个 Wind 引用。鉴于 Java 对类型检查十分严格一个接收一种类型的方法接受了另一种类型看起来很奇怪除非你意识到 Wind 对象同时也是一个 Instrument 对象而且 Instrument 的 tune 方法一定会存在于 Wind 中。在 tune() 中代码对 Instrument 和 所有 Instrument 的派生类起作用这种把 Wind 引用转换为 Instrument 引用的行为称作_向上转型_。 该术语是基于传统的类继承图图最上面是根然后向下铺展。当然你可以以任意方式画你认为有帮助的类图。于是Wind.java 的类图是 继承图中派生类转型为基类是向上的所以通常称作_向上转型_。因为是从一个更具体的类转化为一个更一般的类所以向上转型永远是安全的。也就是说派生类是基类的一个超集。它可能比基类包含更多的方法但它必须至少具有与基类一样的方法。在向上转型期间类接口只可能失去方法不会增加方法。这就是为什么编译器在没有任何明确转型或其他特殊标记的情况下仍然允许向上转型的原因。 也可以执行与向上转型相反的向下转型但是会有问题对于该问题会放在下一章和“类型信息”一章进行更深入的探讨。 再论组合和继承 在面向对象编程中创建和使用代码最有可能的方法是将数据和方法一起打包到类中然后使用该类的对象。也可以使用已有的类通过组合来创建新类。继承其实不太常用。因此尽管在教授 OOP 的过程中我们多次强调继承但这并不意味着要尽可能使用它。恰恰相反尽量少使用它除非确实使用继承是有帮助的。一种判断使用组合还是继承的最清晰的方法是问一问自己是否需要把新类向上转型为基类。如果必须向上转型那么继承就是必要的但如果不需要则要进一步考虑是否该采用继承。“多态”一章提出了一个使用向上转型的最有力的理由但是只要记住问一问“我需要向上转型吗”就能在这两者中作出较好的选择。
http://www.pierceye.com/news/910762/

相关文章:

  • 在网站上显示地图金湖县网站建设
  • 网站域名区别吗模板和网站是一体的吗
  • 百度网盟推广怎么选择投放网站抖音seo代理
  • 电商wordpress网站优化百度
  • phpcms v9 网站搬家南通网站设计专家
  • 延安网站建设推广黄骅市网站建设价格
  • 做网站怎么选关键词网站管理强化阵地建设
  • 网站制作是那个cms 导航网站
  • 网站标题优化技巧房产信息网上自助查询系统
  • wordpress电影网教程合肥网站快速排名优化
  • 药房网站模板网站中英文要怎么做
  • 做影视网站用什么网盘最好wordpress投资主题
  • 潍坊市建设工程质量安全监督站网站网站建设的毕业设计
  • 建筑网站夜里几点维护怎么开发软件app软件
  • 厦门人才网官方网站wordpress 晒单
  • 网站不收录是什么原因网站建设与网页设计试卷
  • html网站模板资源2015做那个网站能致富
  • 设计导航精选最好的设计网站大全商城网站建设开发多少钱
  • 滨州j建设局网站投诉电话检察机关加强网站建设
  • 付费抽奖网站怎么做宁波网站推广营销
  • 单位的网站的建设个人网页制作策划书
  • 在中国可以做国外的域名网站吗企业网查询是什么
  • 网站开发在线浏览pdfwin7可以做网站吗
  • 手机上制作网站的软件巢湖有没有专门做网站的公司
  • 哪里有做企业网站的wordpress 主题类型
  • 什么是网站平台开发工具网站怎么做筛选功能的代码
  • 自建站 外贸军事内参消息
  • 化妆品网站建设实训总结坂田建设网站
  • 成都网站建设哪家专业嘉峪关市建设局网站
  • 企业策划 企业网站建设 品牌设计下载住小帮app看装修