暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Java基础-封装和继承

太子爷哪吒 2021-07-22
290
点击蓝字
默默关注

茫茫人海千千万万,感谢这一秒你看到这里。希望我的文章能对你的有所帮助!共勉!
愿你在未来的日子,保持热爱,奔赴山海!


Java基础知识(封装和继承)



封装

那封装是什么呢?

在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。


1.1 

封装的目的

  • 直接通过操控类对象来达到目的,不需要对具体实现十分了解,使类属性和方法的具体实现对外不可见。不但方便还起到了保护作用。
  • 封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。
  • 适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。


1.2

封装的好处

  • 良好的封装能够减少耦合。
  • 类内部的结构可以自由修改。
  • 可以对成员变量进行更精确的控制。
  • 隐藏信息,实现细节。


1.3

封装的步骤

  1. 修改属性的可见性来限制对属性的访问(一般限制为private),例如:
      public class Person {
      private String name ; // 姓名
      private String gender ; // 性别
      private int age; // 年龄
      }

      这段代码中,将 namesexage 属性设置为私有的,只能本类才能访问,其他类都访问不了,如此就对信息进行了隐藏。


    • 对每个值属性提供对外的公共方法访问,也就是创建一对赋取值方法,用于对私有属性的访问,例如:
        public class Person {
        private String name ; // 姓名
        private String gender ; // 性别
        private int age; // 年龄


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


        public String getName() {
        return name;
        }


        public void setGender(String gender) {
        this.gender = gender;
        }

        public String gender(){
        return gender;
        }

        public void setAge(int age) {
        this.age = age;
        }


        public int getAge() {
        return age;
        }
        }

        采用 this 关键字调用本类中的属性,也就是类中的成员变量。主要为了解决实例变量(private String name)和局部变量(setName(String name)中的name变量)之间发生的同名的冲突。

      1.4

      封装的例子

      • 创建一个用户类User:

        代码如下:
        package com.nz.pojo;


        public class User {
        private String username; // 用户名
        private String password; // 密码


        public String getUsername() {
        return username;
        }


        public void setUsername(String username) {
        this.username = username;
        }


        public String getPassword() {
        return password;
        }


        public void setPassword(String password) {
        this.password = password;
        }
        }


        • 编写测试User的demo:EncapsulationDemo


        • 代码如下:
          package com.nz;


          import com.nz.pojo.User;


          public class EncapsulationDemo {
          public static void main(String[] args) {
          User user = new User();
          user.setUsername("太子爷哪吒");
          user.setPassword("520");
          System.out.println("username: " + user.getUsername() + "-----------"
          + "password: " + user.getPassword());
          }
          }

          执行结果如下:
          username太子爷哪吒-----------password: 520

          1.5

          小结

          封装实际上是将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的访问和操作。就是把我们想提供给外界的一些方法给暴露出来,以便外界能调用到我们。


          继承

          继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。描述的是事物之间的所属关系,这种关系是:is-a
          的关系。


          2.1

          继承的介绍

          就是子类继承父类的属性行为,使得子类对象(实例)可以直接具有与父类相同的属性、相同的行为。子类可以直接访问父类中的非私有的属性和行为。

          2.2

          生活中的继承




          兔子和长颈鹿属于食草动物类,老虎和狮子属于食肉动物类。而食草动物和食肉动物又是属于动物类。
          那是不是兔子、长颈鹿、老虎、狮子都属于动物类呢?答案是没错滴!虽然食草动物和食肉动物都是属于动物,但是两者的属性和行为上有差别,所以子类会具有父类的一般特性也会具有自身的特性。

          我们就可以再多个类中存在相同属性和行为时,我们可以将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那一个类即可。

          2.3

          继承的好处

          1. 提高代码的复用性(减少代码冗余,相同代码重复利用)。
          2. 使类与类之间产生了关系。
          3. 子类拥有父类非 private 的属性、方法。
          4. 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
          5. 子类可以用自己的方式实现父类的方法。
          6. 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。
          7. Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 B 类继承 A 类,C 类继承 B 类,所以按照关系就是 B 类是 C 类的父类,A 类是 B 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。

          2.4

          继承的格式

          在Java当中会通过extends
          关键字可以申明一个类是从另外一个类继承而来的,一般形式如下:
            class 父类 {
            }


            class 子类 extends 父类 {
            }

            需要注意一点:Java 不支持多继承,但支持多重继承。就如下:
              class A {
              }


              class B extends A { (对的)
              }


              class C extends A, B { (错的)
              }


              class C extends B { (对的)
              }


              顶层父类是Object类。所有的类默认继承Object,作为父类。


              2.5

              继承的demo

              • 编写一个父类极其对应的子类信息
                结构如下:


                代码如下:
                父类Person:
                package com.nz.pojo;


                public class Person {
                private String name ;
                private int age ;


                public String getName() {
                return name;
                }


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


                public int getAge() {
                return age;
                }


                public void setAge(int age) {
                this.age = age;
                }
                }

                子类Student没有额外的属性和方法:
                  package com.nz.pojo;


                  /**
                  * 继承了Person特有的name, age,
                  * 没有额外的独有属性和方法
                  */
                  public class Student extends Person{
                  }

                  子类Teacher多了一个工资的属性和独有的教书方法:
                    package com.nz.pojo;


                    /**
                    * 继承了Person特有的name, age,
                    * 多了自己独有的工资属性还有独有的教书方法
                    */
                    public class Teacher extends Person{


                    // 工资
                    private double salary ;


                    // 特有方法
                    public void teach(){
                    System.out.println("老师在认真教书!");
                    }


                    public double getSalary() {
                    return salary;
                    }


                    public void setSalary(double salary) {
                    this.salary = salary;
                    }
                    }


                    • 编写测试代码:
                      package com.nz;


                      import com.nz.pojo.Student;
                      import com.nz.pojo.Teacher;


                      public class InheritDemo {
                      public static void main(String[] args) {
                      Teacher teacher = new Teacher();
                      teacher.setName("太子爷哪吒");
                      teacher.setAge(18);
                      teacher.setSalary(1999.99);
                      System.out.println(teacher.getName());
                      System.out.println(teacher.getAge());
                      System.out.println(teacher.getSalary());
                      teacher.teach();


                      Student student = new Student();
                      student.setName("哪吒");
                      student.setAge(12);
                      //student.setSalary(1999.99); student没有工资属性,报错!
                      System.out.println(student.getName());
                      System.out.println(student.getAge());
                      }
                      }


                      • 结果如下:
                        太子爷哪吒
                        18
                        1999.99
                        老师在认真教书!
                        哪吒
                        12
                        从结果来看,子类继承父类,就可以直接得到父类的成员变量和方法。而子类可以编写一些特有的属性和方法,但是是否可以继承所有成分呢?

                        2.6

                        子类不能继承的内容

                        并不是父类的所有内容都可以给子类继承的。

                        2.6.1 super 与 this 关键字

                        这里先将这两个关键字,super和this在继承关系中,运用比较频繁。
                        • super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
                        • this关键字:指向自己本类的引用。
                          super和this完整的用法如下:
                          this.成员变量 -- 本类的
                          super.成员变量 -- 父类的

                          this.成员方法名() -- 本类的
                          super.成员方法名() -- 父类的


                        • 具体演示,创建测试InheritDemo2:
                            package com.nz;


                            public class InheritDemo2 {
                            public static void main(String[] args) {
                            Animal a = new Animal();
                            a.eat();
                            Cat cat = new Cat();
                            cat.eatFish();
                            }
                            }


                            class Animal {
                            void eat() {
                            System.out.println("animal : eat");
                            }
                            }


                            class Cat extends Animal {
                            void eat() {
                            System.out.println("cat : eat");
                            }
                            void eatFish() {
                            this.eat(); // this 调用自己的方法
                            super.eat(); // super 调用父类方法
                            }
                            }


                          • 调用结果如下:
                            animal : eat
                            cat : eat
                            animal : eat
                          • 注意:
                            子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super()。
                            super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现。


                          2.6.2 构造器不能被继承

                          • 子类不能继承父类的构造器(构造方法或者构造函数),它只是调用(隐式或显式)。因为子类有自己的构造器。值得注意的是子类可以继承父类的私有成员(成员变量,方法),只是子类无法直接访问而已,可以通过getter/setter
                            方法访问父类的private成员变量。

                          • 如果父类的构造器带有参数,则必须在子类的构造器中显式地通过super
                            关键字调用父类的构造器并配以适当的参数列表。

                          • 如果父类构造器没有参数,则在子类的构造器中不需要使用 super
                            关键字调用父类构造器,系统会自动调用父类的无参构造器。

                          • 演示过程:
                              package com.nz;


                              public class InheritDemo3 {
                              public static void main(String[] args) {
                              System.out.println("------Teacher 类继承------");
                              Teacher teacher = new Teacher();
                              Teacher teacher2 = new Teacher("张三");
                              System.out.println("------Student 类继承------");
                              Student student = new Student();
                              Student student2 = new Student("张三三");
                              }
                              }
                              // 父类
                              class Person {
                              private String name;
                              Person(){
                              System.out.println("调用了父类的无参构造器: Person()");
                              }
                              Person(String name) {
                              System.out.println("调用了父类的带参构造器: Person(String name)");
                              this.name = name;
                              }
                              }
                              // Teacher子类继承Person
                              class Teacher extends Person{
                              private String name;
                              Teacher(){
                              // 自动调用父类的无参数构造器 因为会有默认super();
                              System.out.println("Teacher");
                              }


                              public Teacher(String name){
                              super("太子爷哪吒"); // 调用父类中带有参数的构造器
                              System.out.println("Teacher(String name):"+name);
                              this.name = name;
                              }
                              }
                              // Student子类继承Person
                              class Student extends Person{
                              private String name;


                              Student(){
                              super("heihei"); // 调用父类中带有参数的构造器
                              System.out.println("SubClass2");
                              }


                              public Student(String name){ // 自动调用父类的无参数构造器
                              System.out.println("Student(String name):"+name);
                              this.name = name;
                              }
                              }
                            • 结果如下:

                            • ------Teacher 类继承------
                              调用了父类的无参构造器: Person()
                              Teacher
                              调用了父类的带参构造器: Person(String name)
                              Teacher(String name):张三
                              ------Student 类继承------
                              调用了父类的带参构造器: Person(String name)
                              SubClass2
                              调用了父类的无参构造器: Person()
                              Student(String name):张三三

                            2.6.3 final修饰的类不能被继承

                            final 关键字主要用在三个地方:变量、方法、类。
                            1. 修饰类:表示该类不能被继承;
                            2. 修饰方法:表示方法不能被重写;
                            3. 修饰变量:表示变量只能一次赋值以后值不能被修改(常量)。

                            final 的特点:
                            • 对于一个 final 变量,如果是基本数据类型的变量,则其数值一旦在初始 化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不 能再让其指向另一个对象。
                            • 当用 final 修饰一个类时,表明这个类不能被继承。final 类中的所有成员 方法都会被隐式地指定为 final 方法。
                            • 使用 final 方法的原因有两个。第一个原因是把方法锁定,以防任何继承 类修改它的含义;第二个原因是效率。在早期的 Java 实现版本中,会将 final 方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用 带来的任何性能提升(现在的 Java 版本已经不需要使用 final方法进行这些优化了)。类中所有的 private 方法都隐式地指定为 final。
                            我们测试下修饰类后到底能不能继承:
                              package com.nz;


                              public class InheritDemo4 {
                              }


                              // 父类
                              final class Fu {
                              private String name;
                              }


                              //class Zi extends Fu{ Cannot inherit from final 'com.nz.Fu' 会显示没办法继承Fu
                              //}
                              结果:可以看出来在被final修饰的Fu类没办法继承,而且在编译期间就会报错了,没办法通过运行。

                              2.7

                              方法重写

                              2.7.1 介绍

                              子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写或者复写。声明不变,重新实现

                              2.7.2 使用场景与案例

                              发生在子父类之间的关系。子类继承了父类的方法,但是子类觉得父类的这方法不足以满足自己的需求,子类重新写了一个与父类同名的方法,以便覆盖父类的该方法。
                              写个测试案例:
                                package com.nz;


                                public class InheritDemo5 {


                                public static void main(String[] args) {
                                // 创建子类对象
                                Cat lanMao = new Cat();
                                // 调用父类继承而来的方法
                                lanMao.run();
                                // 调用子类重写的方法
                                lanMao.sing();


                                }
                                }


                                class Animal{
                                public void sing(){
                                System.out.println("动物都可以唱歌!");
                                }
                                public void run(){
                                System.out.println("动物都可以跑!");
                                }
                                }


                                class Cat extends Animal {
                                public void sing(){
                                System.out.println("我们一起学猫叫,一起喵喵喵!让我们一起撒个娇");
                                }
                                }

                                运行结果:
                                动物都可以跑!
                                我们一起学猫叫,一起喵喵喵!让我们一起撒个娇
                                可以看出,蓝猫调用了重写后的sing方法。

                                2.7.2 @Override重写注解

                                • @Override:注解,重写注解校验
                                • 这个注解标记的方法,就说明这个方法必须是重写父类的方法,否则编译阶段报错。
                                • 建议重写都加上这个注解,一方面可以提高代码的可读性,一方面可以防止重写出错!
                                  加上后的子类代码形式如下:
                                  class Cat extends Animal {
                                  声明不变,重新实现
                                  方法名称与父类全部一样,只是方法体中的功能重写了!
                                  @Override
                                  public void sing(){
                                  System.out.println("我们一起学猫叫,一起喵喵喵!让我们一起撒个娇");
                                  }
                                  }

                                2.7.3 注意事项

                                1. 方法重写是发生在子父类之间的关系。
                                2. 子类方法覆盖父类方法,必须要保证权限大于等于父类权限。
                                3. 子类方法覆盖父类方法,返回值类型、函数名和参数列表都要一模一样。

                                2.8

                                小结

                                继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承我们能够非常方便地复用以前的代码。

                                : 如果文章有任何错误和建议,请各位大佬尽情留言!如果这篇文章对你也有所帮助,希望可爱亲切的您给个三连关注下,非常感谢啦!




                                END


                                扫码关注我吧

                                生活明朗,万物可爱

                                保持热爱,奔赴山海



                                文章转载自太子爷哪吒,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                                评论