5.继承---黑马程序员

文章详细阐述了Java中的继承特性,包括子类如何继承父类的非私有成员和方法,以及private成员的访问规则。同时,讨论了继承带来的代码复用优势,通过Teacher和Consultant类的例子展示。此外,还提到了继承的注意事项,如权限修饰符的作用范围,以及方法重写的原则和应用场景。最后,介绍了子类构造器的特点,包括如何调用父类构造器以及this关键字的使用。
摘要由CSDN通过智能技术生成

继承

D:\code\黑马\code\oop-up-app\src\com\extend

继承的特点

  • 子类能继承父类的非私有成员变量和成员方法

  • 继承后子类的对象由子类与父类共同组成,每次new出来的对象都是由父类与子类中的所有成员共同组成,所谓的父类中的private无法被继承是指无法访问private修饰的成员,并不是private修饰的成员不存在,就如同单独的一个类中同样无法通过对象去访问它的私有成员

    public class Father {
        public static String Fname = "父类自己的成员";
        public int a;
        private int b;
        public void Fathermethod() {
            System.out.println("父类公共方法");
        }
        private void Fathermethod2() {
            System.out.println("父类私有方法");
        }
        public void setB(int b) {
            this.b = b;
        }
        public int getB() {
            return b;
        }
    }
    
    public class Son extends Father{
        public String Sname = "子类自己的成员";
        public void Sonmethod() {
            System.out.println("子类公共方法");
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            Son s = new Son();
            System.out.println(s.Sname);
            s.Sonmethod();
            System.out.println(Son.Fname);//可以通过类名找父类的静态成员
            s.setB(101);
            System.out.println(s.getB());
    //        s.b;//会报错,子类不能直接访问父类的私有成员,但是可以通过set,get方法访问
    //        s.Fathermethod2();//也不可以访问父类的私有方法
            s.Fathermethod();
        }
    /*
    result:
            子类自己的成员
            子类公共方法
            父类自己的方法
            101
            父类公共方法
    */
    
  • new出的子类对象由子类对象本身和父类共同组成,所占的空间不仅仅有公共成员,也有私有成员。虽然private修饰的父类的私有成员无法直接通过.来访问,但是父类的私有变量同样会在子类对象所存的地址对应的堆内存中开辟空间,可以通过父类方法中的set和get方法来访问

  • 调用父类的public方法时,通过地址找到堆内存中类的地址,再通过类的地址找到子类,然后通过子类找到父类

在这里插入图片描述

继承的好处

  • 减少重复代码的编写

在这里插入图片描述

在这里插入图片描述

public class People {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class Teacher extends People{
    private String skill;

    public String getSkill() {
        return skill;
    }

    public void setSkill(String skill) {
        this.skill = skill;
    }
    public void teach(){
        System.out.println(getName() + "教授" + skill + "课程");
    }
}
public class Consultant extends People{
    private int num;

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public void consult(){
        System.out.println(getName() + "回答了" + num + "次咨询");
    }
}
public class Test {
    public static void main(String[] args) {
        Teacher teacher = new Teacher();
        teacher.setName("张三");
        teacher.setSkill("Java");
        teacher.teach();
        Consultant c = new Consultant();
        c.setName("李四");
        c.setNum(10);
        c.consult();
    }
}
/*
result:
        张三教授Java课程
        李四回答了10次咨询
*/

继承的注意事项

  • 权限修饰符

    -在这里插入图片描述

    • 在本类中四种修饰符修饰的方法都可以被访问

      • public class Father {
            private void printprivate() {
                System.out.println("private method");
            }
        
            void printdefault() {
                    System.out.println("default method");
            }
        
            protected void printprotected() {
                    System.out.println("protected method");
            }
        
            public void printpublic() {
                    System.out.println("public method");
            }
            
        //四个方法都可以被调用
            public void printall() {
                printprivate();
                printdefault();
                printprotected();
                printpublic();
            }
        }
        
    • 在同一包下的其他类

      • public class Test {
            public static void main(String[] args) {
                Father f = new Father();
                // f.printprivate(); // 会报错,因为private方法只能在本类中访问
                f.printdefault();
                f.printprotected();
                f.printpublic();
            }
        }
        
    • 与Father类在不同包下的子类

      • package com.extend.demo4;
        
        import com.extend.demo3.Father;
        
        public class Son extends Father {
            public void printall(){
        //      printprivate(); // 会报错,因为private方法只能在本类中访问
        //      printdefault(); // 会报错,因为default方法只能在本包中访问
                printprotected();
                printpublic();
            }
        }
        
      • package com.extend.demo4;
        
        public class Test {
            public static void main(String[] args) {
                Son s = new Son();
        //        s.printprotected();
        // 也会报错,因为虽然s是子类对象,但是并不是子类本身,所以不能访问protected方法
        //只有在子类中,才能访问producted修饰的方法
            }
        }
        
    • 与Father在不同包下的非子类

      • 	package com.extend.demo4;
        
        import com.extend.demo3.Father;
        
        public class Test {
            public static void main(String[] args) {
                Father f = new Father();
                // f.printprivate(); // 会报错,因为private方法只能在本类中访问
                // f.printdefault(); // 会报错,因为default方法只能在本包中访问
                // 会报错,因为protected方法只能在本包或其他包的子类中访问
                // f.printprotected(); 
                f.printpublic();
            }
        }
        
  • 单继承
    • java是单继承的:一个子类只能继承一个父类,但是一个父类可以被多个子类继承
      • A继承了父类B,就不能再继承其他的父类,但是父类B还可以被C继承
    • java不支持多继承,但是支持多层继承
      • A继承B,B继承C。。。
  • Object
    • Object类是所有类的祖宗,所有类都是Object类的子类或子孙类

方法重写

  • 概念
    • 当子类觉得父类中的某个方法不好用,或者无法满足自己的需求时,子类可以重写一个方法1名称,参数列表均与父类一样的方法来覆盖父类的方法
  • 注意事项
    • 重写后,方法的访问遵循就近原则

    • 使用Override注解表示重写

    • 子类重写父类方法时,访问权限必须大于或者等于父类该方法的权限(public>protected>缺省)。
      重写的方法返回值类型,必须与被重写方法的返回值类型一样,或者范围更小。

    • 私有方法、静态方法不能被重写

      public class Fu {
          public void method() {
              System.out.println("父类方法");
          }
      }
      
      public class Son extends Fu{
          @Override
          public void method() {
              System.out.println("子类方法");
          }
      }
      
      public class Test {
          public static void main(String[] args) {
              Son son = new Son();
              son.method();
          }
      }
      /*
      result:	子类方法
      */
      
  • 应用场景
    • 子类重写Object类的toString方法,返回想要的内容,而不再只是对象的地址
      • sout(对象) == sout(对象.toString( ))

子类中访问其它成员的特点

  • 在子类方法中访问成员变量和成员方法时,按照就近原则
    • 子类方法中访问成员变量优先级:局部变量 > 子类成员变量 > 父类成员变量

    • 子类方法中调用重写的方法,会自动调用子类中重写后的

    • 如果想访问父类成员,需要用super关键字

    • 如果想访问子类成员,需要用this关键字

      public class Father {
          public String name = "父类变量";
          public void say() {
              System.out.println("I am Father");
          }
      }
      
      public class Son extends Father{
          public String name = "成员变量";
          
          @Override
          public void say() {
              System.out.println("I am Son");
          }
      
          public void print() {
              String name = "局部变量";
              System.out.println(name);
              System.out.println(this.name);
              System.out.println(super.name);
              say();
              super.say();
          }
      }
      
      public class Test {
          public static void main(String[] args) {
              Son s = new Son();
              s.print();
          }
      }
      /*
      result:	
              局部变量
              成员变量
              父类变量
              I am Son
              I am Father
      */
      

子类构造器的特点

  • 子类的全部构造器,会先默认调用父类的无参构造器,在执行自己的构造器

    class Fu {
        public Fu() {
            System.out.println("父类构造器");
        }
    }
    
    class Zi extends Fu {
        public Zi() {
            super();//无论写不写,默认存在,指向父类的无参构造器
            System.out.println("子类构造器");
        }
    }
    
    public class Test1 {
        public static void main(String[] args) {
            Zi z = new Zi();
        }
    }
    /*
    result:	
            父类构造器
            子类构造器
    */
    
  • 如果父类没有无参构造器,则必须在子类构造器中显式调用父类的有参构造器

    class Fu {
        public Fu(int a) {
            System.out.println("父类有参构造器");
        }
    }
    
    class Zi extends Fu {
        public Zi() {
            super(3);//显示定义
            System.out.println("子类构造器");
        }
    }
    
    public class test {
        public static void main(String[] args) {
            Zi z = new Zi();
        }
    }
    
    /*
    result:	
            父类有参构造器
            子类构造器
    */
    

子类构造器调用父类构造器的常用应用场景

  • 需要对父类和子类的成员变量同时进行初始化时
class Person {
    private String name;

    public Person() {

    }

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

class Teacher extends Person {
    private String subject;

    public Teacher() {

    }

    public Teacher(String name, String subject) {
        super(name);//调用父类的有参构造器进行赋值
        this.subject = subject;
    }

    public String getSubject() {
        return subject;
    }

    public void setSubject(String subject) {
        this.subject = subject;
    }

    @Override
    public String toString() {
        return super.getName() + "老师的教学科目是" + this.subject;
    }
}

public class Test2 {
    public static void main(String[] args) {
        Teacher t = new Teacher("张三", "Java");
        System.out.println(t);
    }
}
/*
result:	
		张三老师的教学科目是Java
*/

在这里插入图片描述

this(参数)可以调用当前类的兄弟构造器

  • 在任意类的构造器中,都可以通过this(参数)来调用该类的其它构造器

    • 下面代码的需求:如果没有给性别,则默认为男
    class People {
        private String name;
        private int age;
        private char sex;
    
        public People() {
    
        }
        
    	//使用this来调用兄弟构造器
        public People(String name, int age){
            this(name, age, '男');
        }
    
        public People(String name, int age, char sex){
            this.name = name;
            this.age = age;
            this.sex = sex;
        }
    
        @Override
        public String toString() {
            return "People{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", sex=" + sex +
                    '}';
        }
    }
    
    public class Test3 {
        public static void main(String[] args) {
            People p1 = new People("张三", 20);
            System.out.println(p1);
            People p2 = new People("李四", 21, '女');
            System.out.println(p2);
        }
    }
    /*
    result:	
            People{name='张三', age=20, sex=男}
            People{name='李四', age=21, sex=女}
    */
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
继承Java中的一种重要的面向对象编程概念,它允许一个类(子类)继承另一个类(父类)的属性和方法。通过继承,子类可以从父类中获得已有的属性和方法,并且可以在此基础上进行扩展或者修改。 在Java中,使用关键字"extends"来实现继承。子类通过继承父类,可以使用父类中的非私有属性和方法。子类可以直接访问父类的公有属性和方法,也可以通过super关键字来访问父类的构造方法和成员。 下面是一个简单的继承示例: ```java // 父类 class Animal { private String name; public Animal(String name) { this.name = name; } public void eat() { System.out.println(name + "正在吃饭"); } } // 子类 class Dog extends Animal { public Dog(String name) { super(name); } public void bark() { System.out.println("汪汪汪"); } } public class Main { public static void main(String[] args) { Dog dog = new Dog("旺财"); dog.eat(); // 调用父类的eat方法 dog.bark(); // 调用子类的bark方法 } } ``` 在上面的示例中,Animal类是父类,Dog类是子类。Dog类通过关键字"extends"继承了Animal类,从而可以使用Animal类中的属性和方法。在main方法中,我们创建了一个Dog对象,并调用了eat方法(来自父类)和bark方法(来自子类)。 通过继承,子类可以扩展父类的功能,并且可以在需要时覆盖父类的方法来实现特定的行为。继承Java中实现代码重用和多态性的重要手段之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值