标签: javaJavaJAVA
2013-01-22 17:08 1274人阅读 评论(0) 收藏 举报
 分类:
java(58) 读书笔记(46) 

版权声明:本文为博主原创文章,未经博主允许不得转载。

 

目录(?)[+]

 

继承关系

两个类之间存在三种关系:

  1. 依赖,uses-a,如果一个类的方法操纵另一个对象,我们就说一个类依赖于另一个类。
  2. 聚合(关联),has-a,一个对象包含另外一个对象,聚合关系意味着类A的对象包含类B的对象。
  3. 继承,is-a,如果两个类之间存在明显的is-a(是)关系,例如每个经理都是雇员,那这两个类有继承关系。
例如:
  1. class Manager extends Employee{
  2. ......
  3. }
Manager继承了Employee类,继承可以重写超类的方法,也可以添加方法,即子类比超类拥有的功能更加丰富。
 
 

方法重写

当子类重写超类的方法时,也可以调用超类的同名方法,只需要使用super.method()。要注意,重写的方法不可低于超类方法的访问权限!
例如:
  1. //重写getSalary方法
  2. public double getSalary(){
  3. double baseSalary = super.getSalary();//调用了超类的getSalary方法
  4. return baseSalary + bonus;
  5. }

子类重写了getSalary()方法,也调用了超类的同名方法。
另外,super()方法也可以在构造器中使用,以便调用超类的构造器方法。要注意的是super()方法必须是子类构造器的第一条语句。否则编译器会给出Constructor call must be the first statement in a constructor的错误提醒。例子见最后大例子。

 
 

多态和动态绑定

一个对象(例如下例中的e)能够引用多种实际类型的现象称为多态,在运行时能够自动的选择调用那个方法的想象成为动态绑定。Java不支持多重继承,仅支持单继承。
例如下面的大例子中,Emplyee类型的e可以引用Emplyee类型,Manager类型以及Boss类型的对象,当调用e.getSalary()的时候,编译器知道具体的e的实际类型,从而准确的调用该实际类型类的getSalary方法,如果不存在,那就调用其超类的该方法,这就是动态绑定。
 
 

final

阻止继承。
  1. class Employee{
  2. ......
  3. public final String getName(){
  4. return name;
  5. }
  6. ......
  7. }
  8. final class Manager extends Employee{
  9. ......
  10. }

如上例中,Manager类不可以再被继承了,而getName方法也不可被子类重写。

 

强制类型转换

进行强制类型转换的原因:在暂时忽视对象的实际类型之后,使用对象的全部功能。
仅可以在继承链上从上向下进行转换,如把实际类型是Manager的Employee类型的staff[1]转换成Manager类型。
  1. Manager man = (Manager)staff[1];
 

例子

总结性的大例子:
  1. package com.xujin;
  2. public class Test {
  3. public static void main(String[] args) {
  4. Employee[] staff = new Employee[3];
  5. staff[0] = new Employee("Bob", 1000);
  6. staff[1] = new Manager("Jim", 5000, 1000);
  7. staff[2] = new Boss("Alice", 7000, 1000, 10000);
  8. for(Employee e : staff)
  9. System.out.println("class name:" + e.getClass().getName() + "\tid:" + e.getId() +
  10. "\tname:" + e.getName() + "\tsalary:" + e.getSalary());
  11. Manager man = (Manager)staff[1];
  12. Boss boss = (Boss)staff[2];
  13. System.out.println(man.getBonus());//类型转换后就可以使用实际类型的全部功能
  14. System.out.println(boss.getAward());
  15. //ClassCastException异常,不允许进行继承链上的从上到下的转换
  16. //Boss myBoss = (Boss)staff[0];
  17. //把instaceof运算符和类型转换组合起来,避免异常
  18. if(staff[0] instanceof Boss){
  19. System.out.println("staff[0] is a instace of Boss");
  20. Boss myBoss = (Boss) staff[0];
  21. }
  22. else System.out.println("staff[0] isn't a instace of Boss");
  23. if(staff[2] instanceof Boss){
  24. System.out.println("staff[2] is a instace of Boss");
  25. }
  26. else System.out.println("staff[2] isn't a instace of Boss");
  27. }
  28. }
  29. class Employee{
  30. public Employee(String name){
  31. this.name = name;
  32. id = nextId;
  33. nextId++;
  34. }
  35. public Employee(String name, double salary){
  36. this(name);//调用另一构造器
  37. this.salary = salary;
  38. }
  39. //定义访问器方法
  40. public final String getName(){
  41. return name;
  42. }
  43. public double getSalary(){
  44. return salary;
  45. }
  46. public final int getId(){
  47. return id;
  48. }
  49. //定义更改器方法
  50. public final void setName(String name){
  51. this.name = name;
  52. }
  53. public final void setSalary(double salary){
  54. this.salary = salary;
  55. }
  56. public final void raiseSalary(double percent){
  57. this.salary *= (1 + percent);
  58. }
  59. //定义变量
  60. private String name = "";//实例域初始化
  61. private double salary;
  62. private int id;
  63. private static int nextId = 1;
  64. }
  65. class Manager extends Employee{
  66. public Manager(String name, double salary, double bonus){
  67. super(name, salary);//super在构造器中的使用,可以调用超类的构造器
  68. setBonus(bonus);
  69. }
  70. public double getBonus(){
  71. return bonus;
  72. }
  73. //重写getSalary方法
  74. public double getSalary(){
  75. double baseSalary = super.getSalary();//调用了超类的getSalary方法
  76. return baseSalary + bonus;
  77. }
  78. public void setBonus(double bonus){
  79. this.bonus = bonus;
  80. }
  81. private double bonus;
  82. }
  83. final class Boss extends Manager{
  84. public Boss(String name, double salary, double bonus, double award){
  85. super(name, salary, bonus);
  86. this.award = award;
  87. }
  88. //重写getSalary方法
  89. public double getSalary(){
  90. double baseSalary = super.getSalary();//调用了超类的getSalary方法
  91. return baseSalary + award;
  92. }
  93. public double getAward(){
  94. return award;
  95. }
  96. private double award;
  97. }
 

抽象类

最后,阐述一下抽象类的概念。
抽象类就是一个专门用来扩展的祖先类,抽象类本身不能定义一个该类的对象,即抽象类不能被实例化。
  1. Person p = new Student("joun", 17, 6000);

这里p是一个person类型的变量,但是它引用了Student类型的实例。

抽象类中的方法有两种,一种是普通的,和一般类中的方法一样,另一种是抽象方法,起一个占位的作用,将来子类继承会实现这种方法。
类即使不含抽象方法,也可以将类声明为抽象方法。
 
抽象类的抽象方法可以用来实现多态性,例如下例中在抽象类中定义了一个getFee()方法,两个子类Employee和Student分别实现了它,但是用了不同的实现方法,当通过Person类型的p调用getFee()方法时,就会根据p的实际类型来调用确定的方法。
 
  1. package com.xujin;
  2. public class Test {
  3. public static void main(String[] args) {
  4. Person[] people = new Person[2];
  5. people[0] = new Employee("Bod", 34, 5000);
  6. people[1] = new Student("Joun", 17, 6000);
  7. for(Person p: people){
  8. System.out.print(
  9. "Name:" + p.getName() +
  10. "\tAge:" + p.getAge() +
  11. "\tDescription:" + p.getDescription() + "\t");
  12. if(p instanceof Employee){
  13. System.out.println(((Employee) p).getFee());
  14. }
  15. else if(p instanceof Student)
  16. System.out.println(((Student) p).getFee());
  17. }
  18. }
  19. }
  20. abstract class Person{
  21. public Person(String name, int age){
  22. this.name = name;
  23. this.age = age;
  24. }
  25. public abstract String getDescription();
  26. public final String getName(){
  27. return this.name;
  28. }
  29. public final void setName(String name){
  30. this.name = name;
  31. }
  32. public final int getAge(){
  33. return this.age;
  34. }
  35. public final void setAge(int age){
  36. this.age = age;
  37. }
  38. private String name;
  39. private int age;
  40. }
  41. class Employee extends Person{
  42. public Employee(String name, int age, double fee){
  43. super(name, age);
  44. id = nextId;
  45. nextId++;
  46. this.fee = fee;
  47. }
  48. //定义Person抽象类的抽象方法
  49. public String getDescription(){
  50. return "This is an employee. class name:" + this.getClass().getName();
  51. }
  52. //定义访问器方法
  53. public double getFee(){
  54. return fee * 2;
  55. }
  56. public final int getId(){
  57. return id;
  58. }
  59. //定义更改器方法
  60. public final void setFee(double salary){
  61. this.fee = fee;
  62. }
  63. //定义变量
  64. private double fee;
  65. private int id;
  66. private static int nextId = 1;
  67. }
  68. class Student extends Person{
  69. public Student(String name, int age, double fee){
  70. super(name, age);
  71. this.fee = fee;
  72. }
  73. public String getDescription(){
  74. return "This is a student. class name:" + this.getClass().getName();
  75. }
  76. public double getFee(){
  77. return this.fee;
  78. }
  79. public void setFee(double fee){
  80. this.fee = fee;
  81. }
  82. private double fee;
  83. }

结果:

Core Java (十一) Java 继承,类,超类和子类的更多相关文章

  1. java中带继承类的加载顺序详解及实战

    一.背景: 在面试中,在java基础方面,类的加载顺序经常被问及,很多时候我们是搞不清楚到底类的加载顺序是怎么样的,那么今天我们就来看看带有继承的类的加载顺序到底是怎么一回事?在此记下也方便以后复习巩 ...

  2. java基础,继承类题目:编写一个Java应用程序,该程序包括3个类:Monkey类、People类和主类 E

    21.编写一个Java应用程序,该程序包括3个类:Monkey类.People类和主类 E.要求: (1) Monkey类中有个构造方法:Monkey (String s),并且有个public vo ...

  3. Java中的继承:父类和子类的关系

    一.父类引用指向子类对象时 1.若子类覆盖了某方法,则父类引用调用子类重新定义的新方法 2.若子类未覆盖某方法,则父类引用调用父类本身的旧方法 3.若子类覆盖了某属性,但父类引用仍调用父类本身的旧属性 ...

  4. java 继承类与接口问题

    java 先extends 继承类,再implements 继承接口 public class DataBase extends ClassBase implements Ijiekou { }// ...

  5. java中的继承关系

    1.定义 java中的继承是单一的,一个子类只能拥有一个父类:java中所有类的父类是java.lang.Object,除了这个类之外,每个类只能有一个父类: 而一个父类可以有多个子类,可以被多个子类 ...

  6. 黑马程序员——JAVA基础之简述 类的继承、覆写

    ------- android培训.java培训.期待与您交流! ---------- 继承的概述: 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只 ...

  7. Java核心技术第五章——1.类、超类、子类(2)

    继上一篇Java核心技术第五章——1.类.超类.子类(1) 6.重载解析 假如调用ClassName.Method(args) 1.编译器列出类ClassName所有名为Method的方法. 2.编译 ...

  8. Java核心技术第五章——1.类、超类、子类(1)

    1.定义子类: 关键字extends表明正在构造的新类派生与一个已存在的类.已存在的类称为超类.基类或父类:新类称为子类.派生类或孩子类.超类和子类是Java程序员最常用的两个术语(emmm~~我觉得 ...

  9. java第四节 类的继承/抽象/接口/多态性

    /* 类的继承 类的继承可以简化类的定义 java只支持单继承,不允许多重继承 可以有多层继承,即一个类可以继承其一个类的子类,如类B继承了类A,类C又可以继承类B 那么类C也间接继承了类A 子类继承 ...

随机推荐

  1. jQuery 滑动选项卡jQuery tabulous.js

    A jQuery tabs module for todays web! 实例DEMO 运行一下 Documentation Tabulous.js can be used with any cont ...

  2. android 自定义title 报错 You cannot combine custom titles with other title feat

    solution: http://www.apkbus.com/android-80416-1-1.html http://www.eoeandroid.com/forum.php?mod=viewt ...

  3. 用sublime server 启动本地服务器(手机访问电脑页面)

    安装sublime server 插件包           1.Ctrl + shift + p                      install package               ...

  4. python中类变量,成员变量

    参考文献:http://www.jb51.net/article/54286.htm 转载.引用请附上参考文献的链接. (1)位置的区别 先看看下面这段代码: class TestClass(obje ...

  5. DevOps实践

    云计算 [ 01 ]GitLab+Rancher实践DevOps[转载] [ 02 ]Kubernetes CentOS 7.4搭建Kubernetes 1.8.5集群 kubeadm搭建kubern ...

  6. php pdo调用SQLServer存储过程无法获取返回结果

    确定存储过程写的没问题,php调用后,跟踪了语句,也是没问题,就是获取不到返回结果.折腾,搞定. 较之前明确了1. 调用存储过程传参的写法: 2. 获取返回结果集的方法 参考: http://blog ...

  7. 字符串处理scanf("%d%*c",&n);

    "*"表示该输入项读入后不赋予任何变量,即跳过该输入值.这在减小内存开支上面还是有一点用处的,不需要的字符直接跳过,免得申请没用的变量空间 你的例子中的%*c的作用是读入'\n', ...

  8. simulink生成hdl的几个理解

    1,simulink生成hdl的话需要用支持的模块,否则不能生成,支持的模块组成一个库,这个库需要自己生成,用hdllib命令生成,官方原话: The hdllib function creates ...

  9. MYSQL数据库设计之字段选择原则

    关于字段的选择其实很多地方都有进行详细的介绍,我这里只写一下我在使用过程中的心得感受.如果想要全面的了解的话,大家可以去看高性能MYSQL这一本书籍,里面有一章节介绍的特别全面,基本涉及MYSQL中全 ...

  10. 随机生成国内ip

    function rand_ip(){ $ip_long = array( array('607649792', '608174079'), //36.56.0.0-36.63.255.255 arr ...