继承

91 阅读6分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第29天,点击查看活动详情

哈喽,大家好!我是Why,一名在读学生,目前刚刚开始进入自己的编程学习生涯。虽然学习起步较晚,但我坚信做了才有0或1的可能。学了一段时间以后也是选择在掘金上分享自己的日常笔记,也希望能够在众多道友的大家庭中打成一片。 本文主要讲解继承,如果大家读后觉得有用的话,还请大家多多支持博主:欢迎 ❤️点赞👍、收藏⭐、留言💬 ✨✨✨个人主页:JinHuan

继承

实例一

 ​
 // 分析以下程序存在什么问题?代码臃肿。代码没有得到重复利用。
 public class ExtendsTest01{
     public static void main(String[] args){
         // 创建普通账户
         Account act = new Account();
         act.setActno("1111111");
         act.setBalance(10000);
         System.out.println(act.getActno() + ",余额" + act.getBalance());
 ​
         // 创建信用账户
         CreditAccount ca = new CreditAccount();
         ca.setActno("2222222");
         ca.setBalance(-10000);
         ca.setCredit(0.99);
         System.out.println(ca.getActno() + ",余额" + ca.getBalance() + ",信誉度" + ca.getCredit());
     }
 }
 ​
 // 银行账户类
 // 账户的属性:账号、余额
 class Account{
     // 属性
     private String actno;
     private double balance;
 ​
     // 构造方法
     public Account(){
     
     }
     public Account(String actno, double balance){
         this.actno = actno;
         this.balance = balance;
     }
 ​
     // setter and getter
     public void setActno(String actno){
         this.actno = actno;
     }
     public String getActno(){
         return actno;
     }
     public void setBalance(double balance){
         this.balance = balance;
     }
     public double getBalance(){
         return balance;
     }
 }
 ​
 // 其它类型的账户:信用卡账户
 // 账号、余额、信誉度
 class CreditAccount{
     // 属性
     private String actno;
     private double balance;
     private double credit;
 ​
     // 构造方法
     public CreditAccount(){
     
     }
 ​
     // setter and getter方法
     public void setActno(String actno){
         this.actno = actno;
     }
     public String getActno(){
         return actno;
     }
     public void setBalance(double balance){
         this.balance = balance;
     }
     public double getBalance(){
         return balance;
     }
 ​
     public void setCredit(double credit){
         this.credit = credit;
     }
     public double getCredit(){
         return credit;
     }
     
 }

实例二

 ​
 // 使用继承机制来解决代码复用问题。
 // 继承也是存在缺点的:耦合度高,父类修改,子类受牵连。
 public class ExtendsTest02{
     public static void main(String[] args){
         // 创建普通账户
         Account act = new Account();
         act.setActno("1111111");
         act.setBalance(10000);
         System.out.println(act.getActno() + ",余额" + act.getBalance());
 ​
         // 创建信用账户
         CreditAccount ca = new CreditAccount();
         ca.setActno("2222222");
         ca.setBalance(-10000);
         ca.setCredit(0.99);
         System.out.println(ca.getActno() + ",余额" + ca.getBalance() + ",信誉度" + ca.getCredit());
     }
 }
 ​
 // 银行账户类
 // 账户的属性:账号、余额
 class Account{ // 父类
     // 属性
     private String actno;
     private double balance;
 ​
     // 构造方法
     public Account(){
     
     }
     public Account(String actno, double balance){
         this.actno = actno;
         this.balance = balance;
     }
 ​
     // setter and getter
     public void setActno(String actno){
         this.actno = actno;
     }
     public String getActno(){
         return actno;
     }
     public void setBalance(double balance){
         this.balance = balance;
     }
     public double getBalance(){
         return balance;
     }
 }
 ​
 // 其它类型的账户:信用卡账户
 // 账号、余额、信誉度
 class CreditAccount extends Account{ //子类
 ​
     // 属性
     private double credit;
 ​
     // 构造方法
     public CreditAccount(){
     
     }
 ​
     public void doSome(){
         //错误: actno 在 Account 中是 private 访问控制
         //System.out.println(actno);
         // 间接访问
         //System.out.println(this.getActno());
         System.out.println(getActno());
     }
 ​
     // setter and getter方法
     public void setCredit(double credit){
         this.credit = credit;
     }
     public double getCredit(){
         return credit;
     }
     
 }

实例三

 class A
 {
 }
 ​
 class B
 {
 }
 ​
 class C extends A
 {
 }
 ​
 class D extends B
 {
 }
 ​
 // 语法错误
 // java只允许单继承。不允许多继承。java是简单的。C++支持多重继承。
 // C++更接近现实一些。因为在现实世界中儿子同时继承父母两方特征。
 /*
 class E extends A, B
 {
 }
 */
 ​
 class X
 {
 }
 ​
 class Y extends X
 {
 }
 ​
 class M extends X
 {
 }
 ​
 // 其实这也说明了Z是继承X和Y的。
 // 这样描述:Z直接继承了Y,Z间接继承了X
 class Z extends Y
 {
 }
 ​
 /*
 ​
     Z继承了Y
     Y继承了X
     X继承了Object
 ​
     Z对象具有Object对象的特征(基因)。
 ​
     Object是所有类的超类。老祖宗。类体系结构中的根。
     java这么庞大的一个继承结构,最顶点是:Object
 */

实例四

 /*
 测试:子类继承父类之后,能使用子类对象调用父类方法吗
     实际上以上的这个问题问的有点蹊跷!!!!!
     哪里蹊跷?“能使用子类对象调用父类方法”
     本质上,子类继承父类之后,是将父类继承过来的方法归为自己所有。
     实际上调用的也不是父类的方法,是他子类自己的方法(因为已经继承过来了
     就属于自己的。)。
         
 */
 public class ExtendsTest04{
     public static void main(String[] args){
         // 创建子类对象
         Cat c = new Cat();
         // 调用方法
         c.move();
         // 通过子类对象访问name可以吗?
         System.out.println(c.name);
     }
 }
 ​
 // 父类
 //class Animal extends Object {
 class Animal{
     // 名字(先不封装)
     String name = "XiaoHua"; //默认值不是null,给一个XiaoHua
 ​
     // 提供一个动物移动的方法
     public void move(){
         System.out.println(name + "正在移动!");
     }
 }
 ​
 // Cat子类
 // Cat继承Animal,会将Animal中所有的全部继承过来。
 class Cat extends Animal{
 }

实例五

默认继承Object,Object类中有哪些方法呢?

 //默认继承ObjectObject类中有哪些方法呢?
 /*
 public class Object {
      
      // 注意:当源码当中一个方法以“;”结尾,并且修饰符列表中有“native”关键字
      // 表示底层调用C++写的dll程序(dll动态链接库文件)
     private static native void registerNatives();
 ​
      // 静态代码块
     static {
           // 调用registerNatives()方法。
         registerNatives();
     }
 ​
      // 无参数构造方法
     @HotSpotIntrinsicCandidate
     public Object() {}
 ​
      // 底层也是调用C++
     @HotSpotIntrinsicCandidate
     public final native Class<?> getClass();
 ​
      // 底层也是调用C++
     @HotSpotIntrinsicCandidate
     public native int hashCode();
 ​
      // equals方法你应该能看懂。
      // public是公开的
      // boolean 是方法的返回值类型
      // equals 是一个方法名:相等
      // (Object obj) 形参
      // 只不过目前还不知道这个方法存在的意义。
     public boolean equals(Object obj) {
          //方法体
        return (this == obj);
     }
     
      // 已有对象a,想创建一个和a一模一样的对象,你可以调用这个克隆方法。
      // 底层也是调用C++
     @HotSpotIntrinsicCandidate
     protected native Object clone() throws CloneNotSupportedException;
 ​
      // 一会我们可以测试一下toString()方法。
      // public表示公共的
      // String 是返回值类型,toString()方法执行结束之后返回一个字符串。
      // toString 这是方法名。
      // () 表示形参个数为0
     public String toString() {
         return getClass().getName() + "@" + Integer.toHexString(hashCode());
     }
 ​
     @HotSpotIntrinsicCandidate
     public final native void notify();
 ​
     @HotSpotIntrinsicCandidate
     public final native void notifyAll();
 ​
     public final void wait() throws InterruptedException {
         wait(0L);
     }
 ​
     public final native void wait(long timeoutMillis) throws InterruptedException;
 ​
     public final void wait(long timeoutMillis, int nanos) throws InterruptedException {
         if (timeoutMillis < 0) {
             throw new IllegalArgumentException("timeoutMillis value is negative");
         }
 ​
         if (nanos < 0 || nanos > 999999) {
             throw new IllegalArgumentException(
                                 "nanosecond timeout value out of range");
         }
 ​
         if (nanos > 0 && timeoutMillis < Long.MAX_VALUE) {
             timeoutMillis++;
         }
 ​
         wait(timeoutMillis);
     }
     @Deprecated(since="9")
     protected void finalize() throws Throwable { }
 }
 */
 public class ExtendsTest05 {
 ​
     // ExtendsTest05默认继承Object
     // ExtendsTest05类当中是有toString()方法
     // 不过toString()方法是一个实例方法,需要创建对象才能调用。
     /*
     public String toString() {
         return getClass().getName() + "@" + Integer.toHexString(hashCode());
     }
     */
     
     public static void main(String[] args){
 ​
         // 分析这个代码可以执行吗?
         //ExtendsTest05.toString();
 ​
         // 先new对象
         ExtendsTest05 et = new ExtendsTest05();
         String retValue = et.toString();
 ​
         // 2f92e0f4 可以“等同”看做对象在堆内存当中的内存地址。
         // 实际上是内存地址经过“哈希算法”得出的十六进制结果。
         System.out.println(retValue); // ExtendsTest05@2f92e0f4
 ​
         // 创建对象
         Product pro = new Product();
 ​
         String retValue2 = pro.toString();
         System.out.println(retValue2); // Product@5305068a
 ​
         // 以上两行代码能否合并为一行!!!可以
         System.out.println(pro.toString()); //Product@5305068a
 ​
         // 如果直接输出“引用”呢???????
         System.out.println(pro); //Product@5305068a
 ​
         System.out.println(100);
         System.out.println(true);
         // Product@5305068a
         System.out.println(pro); // println方法会自动调用pro的toString()方法。
     }
 }
 ​
 class Product{
     /*
     public String toString() {
         return getClass().getName() + "@" + Integer.toHexString(hashCode());
     }
     */
 }