ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java面向对象(五)

2022-01-22 21:32:03  阅读:88  来源: 互联网

标签:重写 Java 子类 面向对象 test 父类 方法 public


Java面向对象(五)

封装

程序设计的目标

高内聚,低耦合

  • 高内聚:类的内部数据操作细节自己完成,不允许外部干涉
  • 低耦合:仅暴露少量的方法给外部使用

封装的信息隐藏

通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。

封装的关键

  • 属性私有:private

    private将属性私有化,让其它程序不能轻易调用该属性

  • get/set:

    提供可以操作private属性的方法

  • 举例1:

    在类Student里设置私有属性和调出与赋值这些私有属性的get和set

    方法

    public class Student {
        //属性私有(通过private)
        //名字
        private String name;
        //学号
        private int id;
        //性别
        private char sex;
        //提供一些可以操作这个属性的方法
        //提供一些public的get、set方法
        //get获得这个数据
        public String getName(){
            return this.name;//通过getName()获得name属性
        }
        public void setName(String name){
            this.name=name;//通过setName()为name属性赋值
        }
    }
    
    

    在主函数里通过使用类中的set和get方法来实现对私有属性的赋值和调用

    public class Application {
        public static void main(String[] args) {
            Student s1 = new Student();
            s1.setName("史小鹏");//通过Student类里的setName()为name私有属性赋值
            System.out.println(s1.getName());//通过Student类里的getName()获得私有的name属性
        }
    }
    //输出:
    史小鹏
    
  • 举例2:

    关于get/set的应用

    例如可以检测数据是否合法

    Student类

    public class Student {
        //属性私有(通过private)
        //名字
        private String name;
        //学号
        private int id;
        //性别
        private char sex;
        //年龄
        private int age;
        //提供一些可以操作这个属性的方法
        //提供一些public的get、set方法
        //get获得这个数据
        public String getName(){
            return this.name;//通过getName()获得name属性
        }
        public void setName(String name){
            this.name=name;//通过setName()为name属性赋值
        }
    
        public int getId() {
            return id;
        }
    
        public char getSex() {
            return sex;
        }
    
        public void setSex(char sex) {
            this.sex = sex;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            if(age>=0 && age<=100){
                this.age = age;
            }else{
                System.out.println("年龄不合法");
            }
        }
    }
    
    

    主函数

    public class Application {
        public static void main(String[] args) {
            Student s1 = new Student();
            s1.setName("史小鹏");//通过Student类里的setName()为name私有属性赋值
            System.out.println(s1.getName());//通过Student类里的getName()获得私有的name属性
            //输入一个不可能出现的年龄
            s1.setAge(999);
            System.out.println(s1.getAge());
            //输入一个正常年龄
            s1.setAge(20);
            System.out.println(s1.getAge());
        }
    }
    //输出:
    史小鹏
    年龄不合法
    0
    20
    
    

封装的作用

  • 提高程序的安全性,保护数据
  • 隐藏代码的实现细节
  • 统一接口
  • 系统可维护增加了

继承

继承的本质

继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模

继承的关键

  • extands:

    用来进行扩展,子类是父类的扩展

  • Java只有单继承,没有多继承

什么是继承

  • 继承是类和类之间的一种关系(类和类之间的关系:继承、依赖、组合、聚合等)

  • 继承关系两个类:一个为子类(派生类),一个为父类(基类)

  • 子类通过extands继承父类

  • 子类可以重写父类的方法(将子类所继承的方法进行修改而不是)

  • 子类可以继承父类的方法(举例1)

  • 一般子类继承的都是public方法,不能继承private(私有)属性和方法(举例2)

  • 在Java中,所有的类都默认继承Object类

  • 打开继承树:Ctrl+H

  • 举例1:

    • 创建父类

      //人 类
      //父类
      //基类
      public class Person {
          public void say(){
              System.out.println("说了一句话");
          }
      }
      
      
    • 创建子类

      //老师类
      //子类
      //子类继承父类的所有方法
      //派生类
      //老师继承人(老师is人)
      public class Teacher extends Person{
      }
      
      
    • 主函数应用

      public class Application {
          public static void main(String[] args) {
              //通过子类创建对象
              Teacher teacher = new Teacher();
              //因为子类继承父类,所以父类的方法子类对象可以直接使用
              teacher.say();
          }
      }
      //输出:
      说了一句话
      
  • 举例2:

    • 父类

      //人 类
      //父类
      //基类
      public class Person {
          private int a=10;
          int b=10;
          public void say(){
              System.out.println("说了一句话");
          }
          public void say1(){
              System.out.println(a);
          }
      }
      
    • 子类

      //老师类
      //子类
      //子类继承父类的所有方法
      //派生类
      //老师继承人(老师is人)
      public class Teacher extends Person{
      }
      
    • 主函数

      public class Application {
          public static void main(String[] args) {
              //通过子类创建对象
              Teacher teacher = new Teacher();
              //因为子类继承父类,所以父类的方法子类对象可以直接使用
              teacher.say();
              System.out.println(teacher.b);
              teacher.say1();
          }
      }
      
      //输出:
      说了一句话
      10
      10
      

Super

  • super指调用父类

  • 如果子类和父类都定义了相同名字的属性。则在子类中使用属性名或者this.属性名调用的都是子类的属性,而使用super.属性名则调用的是父类属性(举例1)

  • 子类构造器可以调用父类的构造器

  • 子类构造器默认调用了父类的无参构造(举例2)

  • 调用父类的构造器必须放在子类构造器里的第一行(举例2)

  • 调用自身的构造器必须写在第一行this()调用自身无参构造,this(...)调用自身有参构造)

  • super()调用父类无参构造,super(...)调用父类有参构造

  • 调用父类的构造器和调用自身的构造器不能同时存在(因为两个都要求写在第一行)

  • 由于父类写了有参构造之后默认的无参构造就没了,又因为子类构造器默认调用无参构造,所以一旦父类写了无参构造就会导致子类无法写构造器。因此,父类如果要写有参构造就一定要加上一个无参构造或者子类调用父类的有参构造(由于父类写了有参构造导致没有了默认的无参构造,所以不写调用父类有参构造的的话会导致子类构造器默认调用父类的无参构造导致出错)(举例3)

  • 举例1:

    父类:

    //人 类
    //父类
    //基类
    public class Person {
        String name = "father";
    }
    

    子类:

    //学生类
    //子类
    //子类继承父类的所有方法
    //派生类
    //学生继承人(学生is人)
    public class Student extends Person{
        String name = "son";
        public void say(){
            System.out.println(name);//输出子类name属性
            System.out.println(this.name);//输出子类name属性
            System.out.println(super.name);//输出父类name属性
        }
    }
    

    主函数:

    public class Application {
        public static void main(String[] args) {
            Student student = new Student();
            student.say();
        }
    }
    //输出:
    son
    son
    father
    
  • 举例2:

    父类:

    //人 类
    //父类
    //基类
    public class Person {
        String name = "father";
        int age;
        private int b;
        //无参构造方法
        public Person(){
            age=19;
            b=20;
        }
    }
    
    

    子类:

    //学生类
    //子类
    //子类继承父类的所有方法
    //派生类
    //学生继承人(学生is人)
    public class Student extends Person{
        String name = "son";
        String sex ;
        public Student(){
            //调用父类的构造器,必须写在第一行
            super();//默认调用无参构造所以super()可以不用写,如果写的话必须放在第一行
            sex = "man";
        }
        public void say(){
            System.out.println(sex);
            System.out.println(age);
        }
    }
    
    

    主函数:

    public class Application {
        public static void main(String[] args) {
            Student student = new Student();
            student.say();
        }
    }
    //输出:
    man
    19
    
  • 举例3:

    父类:

    //人 类
    //父类
    //基类
    public class Person {
        String name = "father";
        int age;
        //无参构造方法
        public Person(int age){
            this.age=age;
        }
    }
    

    子类1:

    //学生类
    //子类
    //子类继承父类的所有方法
    //派生类
    //学生继承人(学生is人)
    public class Student extends Person{
        String name = "son";
        String sex ;
        public Student(int age){
            //调用父类的有参构造
            super(age);//默认调用无参构造,super()可以不用写,如果写的话必须放在第一行
            sex = "man";
        }
        public void say(){
            System.out.println(sex);
            System.out.println(age);
        }
    }
    
    

    子类2:

    //老师类
    //子类
    //子类继承父类的所有方法
    //派生类
    //老师继承人(老师is人)
    public class Teacher extends Person{
        public Teacher(){
            //调用父类的有参构造
            super(50);
        }
    }
    
    

    主函数:

    public class Application {
        public static void main(String[] args) {
            Student student = new Student(30);
            Teacher teacher = new Teacher();
            student.say();
            System.out.println(teacher.age);
        }
    }
    //输出:
    man
    30
    50
    
super与this
super的注意点:
  • super调用父类的构造方法,必须在构造方法的第一个
  • super必须只能出现在子类的方法或者构造方法中
  • super和this不能同时调用构造方法
super VS this:
  • 代表的对象不同:
    • this:本身调用这个对象
    • super:代表父类对象的应用
  • 前提:
    • this:没有继承也可以使用
    • super:只能在继承条件下才可以使用
  • 构造方法:
    • this():本类(自己)的构造
    • super():父类的构造

重写

  • 重写都是对方法的重写,和属性无关

  • 静态的方法和非静态的方法有区别,区别很大(举例1,举例2)

  • 只有动态方法里的才算重写

  • 重写的快捷键:Alt+Insert :override

  • 举例1(静态方法里):

    父类:

    //重写都是对方法的重写,和属性无关
    public class B {
        //静态方法
        public static void test(){
            System.out.println("B=>test()");
        }
    }
    

    子类:

    public class A extends B {
        //A类对父类中的test()方法进行重写
        //静态方法
        public static void test(){
            System.out.println("A=>test()");
        }
    }
    

    主函数:

    public class Application {
        public static void main(String[] args) {
            //方法的调用只和左边,定义的数据类型有关
            A a = new A();
            a.test();
            //父类的引用指向了子类
            B b = new A();
            b.test();
        }
    }
    //输出:
    A=>test()
    B=>test()//子类没有重写父类的方法(因为是静态方法)
    
  • 举例2(动态方法里的重写):

    父类:

    //重写都是对方法的重写,和属性无关
    public class B {
        public void test(){
            System.out.println("B=>test()");
        }
    }
    

    子类:

    public class A extends B {
        //A类对父类中的test()方法进行重写
        public void test(){
            System.out.println("A=>test()");
        }
    }
    

    主函数:

    public class Application {
        public static void main(String[] args) {
            //方法的调用只和左边,定义的数据类型有关
            A a = new A();
            a.test();
            //父类的引用指向了子类
            B b = new A();//子类重写了父类的方法
            b.test();
        }
    }
    //输出:
    A=>test()
    A=>test()//子类重写了父类的方法
    

重写注意事项:

  • 需要有继承关系,子类重写父类的方法

  • 方法名必须相同

  • 参数列表列表必须相同

  • 修饰符:范围可以扩大(不能缩小):public>Protected>Default(默认)>private

    例如:父类中的方法是Default,则子类可以重写方法为public或Protected(扩大)

  • 抛出的异常:范围,可以缩小,但不能扩大:ClassNotFoundException-->Exception(大)

重写的原因:

  • 父类的功能,子类不一定需要,或者不一定满足

多态

  • 多态可以实现动态编译:类型:可扩展性

  • 一个对象的实际类型是确定的,但一个对象的引用类型是不确定的

    举例:

    //父类Person(),子类Student()
    Student s1 = new Student();//new Student()是对象的实际类型(确定的)
    //可以指向的引用类型是不确定的,父类的引用指向子类
    Person s2 = new Student();//Person是引用类型
    Object s3 = new Student();
    
  • 父类的引用指向子类时,如果父类方法在子类中被重写,则调用的方法是子类方法;如果不被重写,则调用的方法是父类方法

    举例1(被重写):

    父类:

    //重写都是对方法的重写,和属性无关
    public class B {
        public void test(){
            System.out.println("B=>test()");
        }
    }
    

    子类:

    public class A extends B {
        //A类对父类中的test()方法进行重写
        public void test(){
            System.out.println("A=>test()");
        }
    }
    

    主函数:

    public class Application {
        public static void main(String[] args) {
            //方法的调用只和左边,定义的数据类型有关
            A a = new A();
            a.test();
            //父类的引用指向了子类
            B b = new A();//子类重写了父类的方法
            b.test();
        }
    }
    //输出:
    A=>test()
    A=>test()//子类重写了父类的方法
    

    举例2(不被重写):

    父类:

    //重写都是对方法的重写,和属性无关
    public class B {
         void test(){
            System.out.println("B=>test()");
        }
    }
    

    子类:

    public class A extends B {
    }
    
    

    主函数:

    public class Application {
        public static void main(String[] args) {
            //方法的调用只和左边,定义的数据类型有关
            A a = new A();
            a.test();
            //父类的引用指向了子类
            B b = new A();
            b.test();
        }
    }
    //输出:
    B=>test()
    B=>test()
    
  • 设A是父方法,B是子方法,经过A b = new B();(父类指向引用)之后,调用方法 a.say() :

    • 如果A(父类)没有say()方法而B(子类)有say()方法,则无法调用say()方法;

    • 如果A有say()方法B没有重写say()方法,则调用A的say()方法;

    • 如果A有say()方法但是B重写say()方法,则调用B的say()方法;

  • 设A是父方法,B是子方法,经过B b = new B();(子类指向引用)之后,调用方法 a.say() :

    • 如果A(父类)没有say()方法而B(子类)有say()方法,则调用B的say()方法;

    • 如果A有say()方法B没有重写say()方法,则调用A的say()方法;

    • 如果A有say()方法但是B重写say()方法,则调用B的say()方法;

  • 综上两点:

    • 子类能调用的方法都是自己的或者继承父类的
    • 父类可以指向子类(能调用子类重写的方法),但不能调用子类独有的方法

多态注意事项:

  • 多态是方法的多态,属性没有多态

  • 父类和子类,有联系,(父子类型转换异常:ClassCastException)

  • 多态存在的条件:

    1. 有继承关系
    2. 方法需要重写
    3. 父类引用指向子类对象
  • 不支持重写的:

    1. static 方法:属于类,不属于实例
    2. final 常量:
    3. private 方法:私有方法

标签:重写,Java,子类,面向对象,test,父类,方法,public
来源: https://www.cnblogs.com/sxw0514/p/15835104.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有