封装,继承,多态

封装,继承,多态

封装

  1. 高内聚,低耦合。高内聚:是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。(比如:去取钱,普通用户才可以,银行的总额大家不能操作,大家只能操作的自己卡的金额,方法是有限的)

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

  3. 属性私有:get/set。

  4. 代码如下:new这个Student类之后就会返回一个学生的对象s1。(对一个对象,一个类的封装)

    package oop.demo01.demo04;

    //1.提高程序的安全性,保护数据
    //2.隐藏代码的实现细节
    //3.统一接口,所有的方法都是get/set,形成了一个规范,用户调用的接口就是这个
    //4.系统可维护性增加了
    public class Application {
       public static void main(String[] args) {
           Student s1 = new Student();
           s1.id = 3;    //属性学号id可以直接调用赋值,通常都设为private私有化。
           //s1.name = "zhangsan"; //属性名字不可以直接赋值,会报错,因为在Student类中private String name;属性是私有的。

           s1.setName("zhangsan");  //setName方法需要单写,因为方法没有返回值
           System.out.println(s1.getName()); //getName有返回值
           //方法名,参数名都相同,方法一定相同。
           System.out.println(s1.setName("lisi"));  

           s1.setAge(100);      
           System.out.println(s1.getAge());   //打印输出的是必须要有返回值的方法
      }
    }

代码二:

package oop.demo01.demo04;

public class Student {
   //属性私有
   private String name;  //名字
   int id;    // 学号 默认为public
   private char sex;  // 性别
   private int age;

   //提供一些可以操纵这些属性的方法:get、set方法
   //get 获得这个数据
   public String getName(){
       return this.name;
  }
   //set 给这个数据设置值
   public String setName(String name){    //给这些属性赋值
       this.name = name;
       return this.name;        //改写成有返回值的方法
  }

   //alt + insert     getter and setter
   //自动生成get set 方法

   public char getSex() {
       return sex;
  }

   public void setSex(char sex) {
       this.sex = sex;
  }

   public int getAge() {
       return age;
  }

   public void setAge(int age) {   //可以添加验证性的安全性的判断
       if(age<120 && age>0){    //有setAge方法,可以在方法中对输入值进行判断。直接赋值无法进行条件判断
           this.age = age;    //输入100,输出100
      }else{
           age = 3;          //输入999,输出0,因为并没有给Student类的age属性赋值。
      }
  }

   //学习()
   //睡觉()
}

继承

  1. 继承的本质是对某一批类的抽象,从而实现的世界的建模。 (类之间的关系还有依赖,组合,聚合)。

  2. extends意思是“扩展”,子类是父类的扩展。子类继承父类。

  3. java类中只有单继承,没有多继承。(一个儿子只能有一个爸爸,一个爸爸可以有多个儿子)。

  4. 代码如下:父类

    package oop.demo01.demo05;

    //父类:Person类   子类继承父类,会拥有父类的全部方法(public)
    public class Person {
       public int money = 10_0000_0000;
       private int bank = 123;    //私有的东西无法继承
       // default默认的,protected受保护的; 四个修饰符 public,protected,default,private优先级从高到低
       //一般属性才是私有的,要继承的对象都是public.
       public void say(){
           System.out.println("说了一句话");
      }

       public int getBank() {
           return bank;
      }

       public void setBank(int bank) {
           this.bank = bank;
      }
    }

    子类:

    package oop.demo01.demo05;

    //学生也是人,用extends继承 人这个类。
    //Student类:派生类,子类
    public class Student extends Person{
       //Ctrl+H 打开继承树,继承的结构
    }

子类二:

package oop.demo01.demo05;

//每一个类可以创建出很多对象。两个独立的类可以进一步抽象,抽象出一个父类Person。形成树状图的感觉。(宏观的把握)(封装底层)
//Teacher类:派生类,子类
public class Teacher {

}

测试类:

package oop.demo01.demo05;

public class Application {
   public static void main(String[] args) {
       Student student = new Student();  //创建一个student对象
       student.say();
       System.out.println(student.money);

       //有一个看不见的类Object,但是它存在,像无参构造方法一样
       //在java中,所有类都默认直接或间接继承Object类。(这个类中有很多本地的方法native)
       //所以不用写extends Object。
  }
}

super类

  1. 注意点:super是调用父类的构造方法,必须在构造方法放入第一个。

  2. super必须只能出现在子类的方法或构造方法中。

  3. super和this不能同时调用构造方法。

  4. this:本身调用者这个对象。super:代表父类对象的应用。

this:没有继承也可以使用。super:在继承条件下,才可以使用。

构造方法:this();本类的构造。(this可以调用本类的其他方法) super();父类的构造。

  1. 代码如下:

package oop.demo01.demo05;

public class Application {
   public static void main(String[] args) {
       Student student = new Student();
       //student.test("张三");
       //student.test1();

  }
}

代码二:

package oop.demo01.demo05;

//父类:Person类   子类继承父类,会拥有父类的全部方法(public)
public class Person {
   public Person() {//alt+insert-->constructor,select none生成无参构造方法
       System.out.println("Person无参执行了");
  }

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

   protected String name = "zhangsan";

   public void print(){
       System.out.println("Person");
  }
   private void print1(){  //私有的方法无法被继承
       System.out.println("zs");
  }
}

代码三:

package oop.demo01.demo05;

//学生也是人,用extends继承 人这个类。
//Student类:派生类,子类
public class Student extends Person{
   public Student() {   //无参构造内部方法体是空的
       //隐藏代码:先调用了父类的无参构造
       super();//调用父类的构造器,必须要在子类构造器中代码的第一行运行。
       //this("hello"); //调用自己类的构造器,构造方法this();
       //在无参构造方法中,调用其它构造器,要么调用父类的,要么调用子类的,只能在代码的第一行,只能二选一。
       //在父类中,重写了有参构造,必须要把无参构造加上,否则后面的子类全都会报错。
       //super("zhangsan");调用父类的有参构造
       System.out.println("Student无参执行了");
  }

   public Student(String name) { //有参构造
       this.name = name;
  }

   private String name = "lisi";

   public void print(){
       System.out.println("Student");
  }

   public void test1(){
       print();   //Student 输出当前这个类的
       this.print();  //Student
       super.print();  //Person 调用了父类的方法
       //super.print1(); 私有的无法继承,会报错。
  }

   public void test(String name){
       System.out.println(name);   //张三   实参赋给形参的值
       System.out.println(this.name);  //lisi   当前类的属性
       System.out.println(super.name);  //zhangsan   调到父类的属性
  }

}

方法的重写

代码一:静态方法案例前三个

package oop.demo01.demo05;

public class B {
   public static void test(){
       System.out.println("B-->test");
  }
}

代码二:

package oop.demo01.demo05;

public class A extends B{   //继承
   public static void test(){
       System.out.println("A-->test");
  }
}

代码三:

package oop.demo01.demo05;

public class Application {
   public static void main(String[] args) {
       //静态方法的调用只和左边定义的数据类型有关。
       A a = new A();
       a.test();   //A-->test
       // 父类的引用b指向了子类
       B b = new A();  //执行实例化的过程,就是要先进入A类的无参构造方法,A继承了B,在无参构造方法中第一行先运行了B类的无参构造,所以new A()可以实现B类型的对象。
       b.test();   //B-->test
  }
}    

代码四:静态方法和非静态方法区别很大

总结:重写需要有继承关系,子类重写父类的方法(不能重写属性),方法名,参数列表必须相同;修饰符范围可以扩大(public>protected>default>private);抛出的的异常:范围可以被缩小,但不能被扩大;比如:ClassNotFoundException-->Exception(变大)不行;

重写:子类和父类的方法必须一致,方法体不同。因为父类的功能,子类不一定需要或不一定满足。

代码五:

package oop.demo01.demo05;

public class B {

   public void test1(){
       System.out.println("B-->test");
  }
}

代码六:

package oop.demo01.demo05;

public class A extends B{   //继承
   //Override 重写   alt+insert -->override method-->test1,A类中有方法的时候是不能重写的。
   @Override  //注解:有功能的注释 父类的方法是static,子类的也需要是,否则A类不能重写方法
   public void test1() {   //重写的关键词只能是public,不能是私有的     //最后都经过此方法,所以值为A-->test
       //super.test1();   //默认调用了父类的test1();
       System.out.println("A-->test");  //可以在方法体中重写自己的方法,      
  }
}

代码七:

package oop.demo01.demo05;

public class Application {
   public static void main(String[] args) {
       //方法的调用只和左边定义的数据类型有关。
       //A a = new A();
       //a.test();   //A-->test
       // 父类的引用b指向了子类
       //B b = new A(); //执行实例化的过程,就是要先进入A类的无参构造方法,A继承了B,在无参构造方法中第一行先运行了B类的无参构造,所以new A()可以实现B类型的对象。
       //b.test();   //B-->test

       A aa = new A();
       aa.test1();    //A-->test
       B bb = new A();  //子类重写了父类的方法,只与非静态方法有关。
       bb.test1();    //A-->test  
  }
}

多态

  1. 动态编译:类型:可扩展性

  2. 多态:即同一方法可以根据发送对象的不同(类型,重写)而采取多种不同的行为方式。

  3. 一个对象的是实际类型new A()是确定的,但可以指向对象的引用的类型A a,B b有很多(父类,有关系的类)。A a = new A();B b = new A();

  4. 多态存在的条件:有继承关系,子类重写父类的方法,父类引用B b指向子类对象new A()。(father f1 = new son();)

  5. 代码如下:

  6. 注意事项:多态是方法的多态,属性没有多态;父类和子类要有联系,类型不同强转会报错,比如:ClassCastException,类型转换异常;同一方法名,哪一个类(型)的,执行哪个类(型)对应的方法;

  7. 一些方法不能被重写:static方法:属于类,不属于任何一个实例(对象),和类相关;final:常量池中;private:私有的,不能被继承。

    package oop.demo01.demo06;

    public class Application {
       public static void main(String[] args) {
           //一个对象的是实际类型是确定的,new Student();
           //new Student();   那这个Student的类型肯定是确定的Student类
           //new Person();

           //可以指向的引用类型就不确定了: 父类的引用类型指向子类的类型。(可以指向这个对象的引用类型是任意的,父类型即可)

           //Student能调用的方法都是自己的或者继承父类的。
           Student s1 = new Student();  //都是学生new Student(),但表现出了多种状态Student s1,Person s2。
           //Person父类,虽然可以指向子类,但不能调用子类独有的方法。
           Person s2 = new Student();  //父类的引用指向子类的类型 String s2不行,String与Student没有关系。
           Object s3 = new Student();

           //对象能执行哪些方法,主要看对象左边的类型,和右边关系不大。Person s2 = new Student();
           s2.run();  //run 虽然我们new的是Student,但依旧走了父类的方法,因为子类继承了父类的全部方法
           s1.run();  //一旦子类重写了父类的方法, s1.run();,s2.run();都执行子类的方法,结果为son。
           //s2.eat(); //对象变量类型是Person类型的s2中,Person类中没有eat方法,所以调用不了。如果子类和父类都有eat方法,只要子类没有重写父类,就调用父类的方法,如果重写了,就调用子类的方法。
          ((Student)s2).eat();  //强制类型转换 Person->Student类型,高转低,s2的类型转换成Student类型,就可以调用Student类型中的方法了。
           s1.eat(); //s1的 Student类型中有eat方法,所以可以调用。
      }
    }

    父类:

    package oop.demo01.demo06;

    public class Person {
       public void run(){
           System.out.println("run");
      }
    }

子类:

package oop.demo01.demo06;

public class Student extends Person {
   @Override
   public void run() {
       System.out.println("son");   //重写父类的方法
  }

   public void eat(){
       System.out.println("eat");
  }
}

 

posted @ 2021-01-31 18:22  爱罗翔的张三  阅读(239)  评论(0编辑  收藏  举报