面向对象---封装,继承,多态

构造方法

​ 方法名和类名相同,和普通方法格式不一样的特殊方法。

作用

  1. 用来构造对象;
  2. 对对象属性初始化。

特点

  1. 没有返回类型;
  2. 没有返回值,有return,一般不写

注意事项

  1. 普通方法名称可以与类名相同;
  2. 重载构造方法后,默认无参构造方法失效;

static关键字

​ 静态修饰符,可以修饰成员变量和成员方法,主要作用在于创建独立于具体对象的域变量或方法

特点

  1. static修饰的成员不属于任何实例对象,被所有实例对象共享;
  2. 在类被加载时,就会加载静态成员,即静态成员优先于对象存在内存中,类加载完毕后可直接用类名访问。

注意事项

  1. 静态方法中不能用this关键字,因为静态方法随之类加载而加载,而this随着对象创建而存在,静态优先于对象存在;
  2. 静态可以访问静态,但不能访问非静态;
  3. 非静态可以访问静态,和非静态。

封装

​ 封装是指隐藏对象的属性和方法实现细节,仅对外提供公共访问方式,设置方法和属性访问权限。

特点

  1. 隐藏功能实现过程,外界只需要通过公共的访问方式访问即可;
  2. 提高代码重用性;
  3. 提高代码安全性;
  4. 提高代码可维护性。

实现封装---private

​ 封装通常给成员加上private关键字达到隐藏效果。private修饰的成员只能在本类中访问。

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

    public int getAge(){
      return age;
    }

    public String getName(){
      return name;
    }

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

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

注:private不等于封装,private只是用于控制访问权限的一种方式。

继承

​ 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,多个类只需要继承那个类。

​ 多个类称为子类、派生类;单独这个类称为父类、超类、基类。

优势

  1. 提高代码复用性;
  2. 提高代码维护性;
  3. 继承是多态的前提。

劣势

  1. 造成类与类间的强关联,即高耦合。
  2. 修改父类对子类造成影响。

特点

  1. Java中,类只支持单继承,不可以多继承;
  2. 类可以多重继承,不可以循环继承。

注意事项

  1. 父类构造方法不能被继承,可以使用super关键字去访问父类构造方法;
  2. 子类可以继承父类中非私有成员,不能继承父类私有成员,即子类不能直接使用父类私有成员;
  3. java在创建一个子类对象时,首先调用父类不带参数的构造方法,生成父类对象,然后调用子类构造方法,生成子类对象。

继承中构造方法的关系

  1. 子类中所有构造方法第一行默认都是super();

    ​ 因为父类成员可以在子类中被调用,则父类必须要被初始化,所以在子类构造函数中默认调用父类构造函数,目的是初始化父类对象。

  2. 子类中所有的构造方法,第一行必须是super(参数)或this(参数),他们不可以共存;

    class A 
    {
        A()
       {
            System.out.println("You call super class non-args constructor!");
       }
    }
    
    class B extends A
    {
          B()
          {
              //这里,编译器将自动加上 super();
              System.out.println("You call subclass constructor!");
          }
           
           B(String n)
           {
               super();
               this();
               //实际就是调用了B(){...},而在B(){...}中编译器自动加上了super();这样就相当于两次调用了super();也就是说对父类进行了两次初始化。而在实例化一个对象时,一个构造方法只能调用一次,这说明this和super不能同时存在一个构造方法中。
               //同时因为系统没有在第一行发现this()或super()调用,就会自动加上super(),如果没有将this()和super()放在第一行就会产生矛盾。因为总有一个super()在第二句上。所以该程序不能通过编译!!!
             }
    
  3. 子类中所有的构造方法,至少有一个构造方法里面调用的是super(参数)。

    ​ 根据第一条必须要初始化父类对象,第二条this()和super()不能共存于一个构造函数中,所以必须保证有一个构造函数执行了父类构造方法。

    class Fu {}
    			
    class Zi extends Fu {
        public Zi() {
            this("aaa");
        }
    
        public Zi(String name) {
            this(18);
        }
    
        public Zi(int age) {
            this("aaa", 18);
        }
    
        public Zi(String name, int age) {
            //super();
        }
    }
    

重写(Override)

​ 在子类中申明与父类的方法完全一致的方法,就成为方法重写。

​ 在子类方法的声明上面加上@Override即表示方法重写,可不加。

重写(Overide)与重载(Overload)

​ 重载:在同一个类中,两个方法名字相同,参数列表不同;

​ 重写:子类中的方法声明与父类中的方法声明完全一致。

注意事项

  1. 子类不能重写父类私有成员方法;

  2. 子类的方法访问权限修饰符要>=父类方法的访问权限修饰符;

  3. 子类方法的返回值类型可以与父类方法的返回值类型不一致,但是父类方法返回值类型和子类方法返回值类型要有继承关系

    class Fu {
        public A print() {
            System.out.println("fu...");
            return new A();
        }
    }
    
    class Zi extends Fu {
        @Override
        public B print() {
            System.out.println("zi...");
            return new B();
        }
    }
    
    class A{}
    class B extends A{}
    
    1. 静态方法只能重写静态方法。

this关键字和super关键字

this

​ 代表当前对象的引用。

作用

​ 区分重名局部变量和成员变量;

​ 调用当前类的成员变量,方法及构造方法。

super

​ super是父类内存空间的标记,可以当做父类对象的引用来使用,但不能说super就是父类对象的引用

作用

​ 在子类中调用直接父类构造函数;

​ 在子类中调用直接父类非私有成员。

super和this关键字的使用:

​ 调用构造方法:

​ super(参数); //调用父类构造方法

​ this(参数); //调用本类构造方法

​ 调用成员方法:

​ super.方法名(); //调用父类中的成员方法

​ this.方法名(); //调用本类中的成员方法

​ 调用成员变量:

​ super.变量名; //调用父类中的成员变量

​ this.变量名; //调用本类中的成员变量

多态

​ 一个对象在不同的时刻,表现出来的不同状态;多态体现为父类引用变量可以指向子类对象

​ 多态是同一个行为具有多个不同表现形式或形态的能力;

​ 多态就是同一个接口,使用不同的实例而执行不同操作。

多态存在的三个必要条件

​ 继承,重写,父类引用指向子类对象。

多态中成员的特点

成员变量

  1. 父类引用中不能使用子类中特有的成员变量;

  2. 父类引用只能使用自身带的成员变量,不能使用子类中成员变量。

    public class Demo01 {
        public static void main(String[] args) {
            Fu fu = new Zi();
            System.out.println(fu.i);//1
            System.out.println(fu.j);//编译报错
        }
    }
    
    class Fu {
        int i = 1;
    }
    
    class Zi extends Fu {
        int i = 2;
        int j = 3;
    }
    

口诀:多态调用成员变量时,编译看左边,运行看左边。

成员方法

  1. 父类引用不能使用子类中特有的成员方法;

    public class Demo01 {
        public static void main(String[] args) {
            Fu fu = new Zi();
            fu.printFu();//fu
            fu.printZi();//编译报错
        }
    }
    
    class Fu {
        public void printFu() {
            System.out.println("fu");
        }
    }
    
    class Zi extends Fu {
        public void printZi() {
            System.out.println("zi");
        }
    }
    
  2. 父类引用可以使用子类中重写父类的方法。

    public class Demo01 {
        public static void main(String[] args) {
            Fu fu = new Zi();
            fu.print();//zi
            fu.print();//zi
        }
    }
    
    class Fu {
        public void print() {
            System.out.println("fu");
        }
    }
    
    class Zi extends Fu {
        public void print() {
            System.out.println("zi");
        }
    }
    

口诀:多态调用成员方法,编译看左边,运行看右边。

静态成员

  1. 父类引用不能使用子类中特有静态成员变量;

  2. 父类引用不能使用子类重写的静态成员方法。

    public class Demo01 {
        public static void main(String[] args) {
            Fu fu = new Zi();
            System.out.println(fu.i);//1
            System.out.println(fu.j); //编译报错
            fu.print(); //fu
        }
    }
    
    class Fu {
        static int i = 1;
    
        public static void print() {
            System.out.println("fu");
        }
    }
    
    class Zi extends Fu {
        static int j = 2;
    
        public static void print() {
            System.out.println("zi");
        }
    }
    

口诀:多态调用静态成员变量和方法,编译看左边,运行看左边。

优势

  1. 提高可扩展性。

    ​ 父类引用作为形参,子类对象作为实参。

劣势

​ 1. 父类引用不能使用子类中特有的成员。

向上转型与向下转型

向上转型

​ 多态本身就是向上转型的过程,Fu fu = new Zi();

适用场景

​ 当不需要面对子类类型时,通过提高扩展性,或者使用父类的功能就能完成相应的操作。

向下转型

​ 已经向上转型的子类对象可以使用强制类型转换,将父类引用类型转为子类引用类型,Zi zi = (Zi)fu;

注:向下转型的类型需要有继承关系。

public class Demo01 {
    public static void main(String[] args) {
        Fu fu = new Zi();
        Zi1 zi1 = (Zi1)fu;//编译不会报错,运行会报类型转换异常
        zi1.print();
    }
}

class Fu {
    public static void print() {
        System.out.println("fu");
    }
}

class Zi extends Fu {
    public static void print() {
        System.out.println("zi");
    }
}

class Zi1 extends Fu{
    public static void print() {
        System.out.println("zi1");
    }
}
适用场景

​ 当要使用子类特有功能时。

posted @ 2021-11-14 23:03  舟洲文  阅读(50)  评论(0)    收藏  举报