面向对象语言三大特征——封装、继承、多态

目录

封装

封装的概念

封装的好处

继承

继承的概念

继承的传递性

继承中的构造方法

方法的重写(OverRide)

重写与重载区别

抽象类

抽象方法

抽象类的定义

抽象类的特点

多态


封装

封装的概念

      封装:将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。

封装的好处

  • 只能通过规定好的方法才能访问
  • 方便加入控制语句
  • 隐藏类的实现细节
  • 方便修改实现

具体的表现方式是使用get/set方法来实现

public class Demo{
      private int id;
      public int getID(){
          return id;
   }
      public int setID(int id){
          this.id=id;
   }

}

继承

继承的概念

继承:继承是从已有的类中派生出新的类,新的类能吸收已有类的属性和行为,并在此基础上拓展自己新的属性以及行为。

拿JAVA为例子:

  • 在JAVA中使用extends关键字来表示继承关系。
  • JAVA不支持多继承,只能单继承,单继承使JAVA的继承关系很简单,一个类只能有一个直接父类。
  • 继承之后子类可以调用父类的所有非私有属性和非私有方法。

继承是代码重用的一种方式

继承的形式

[访问权限修饰符] [修饰符] 子类名 extends 父类名{子类体}

public class Animal{
    public void eat(){}
}
public class Dog extends Animal{
    public void play(){} 
}
//子类对象可以直接调用父类的方法,强调复用性 
Dog dog = new Dog ();
dog.eat();

Dog类是Animal类的子类,Animal类是Dog类的父类

Dog类是Animal类的派生类,Animal类是Dog类的基类

继承的传递性

C类从B类继承,B类又从A类继承

那么C类就具有B类和A类的所有非私有属性和非私有方法

当一个没有继承任何一个类时,jvm会默认让类继承Object类Object是java为所有类提供的基类

public class A {
    String name;
    public A(String name){
        this.name=name;
    }
    public void speak(){
        System.out.println("A说话");
    }
    public void cry(){
        System.out.println("A哭");
    }
}
class  B extends A{
    public B(String name){
        super(name);
    }
    @Override
    public void cry() {
        System.out.println("B哭");
    }
}
class C extends  B{
    public C(String name){
        super(name);
    }
    @Override
    public void cry() {
        System.out.println("C哭");
    }
}
public class Test {
    public static void main(String[] args) {
        A a=new A("a");
        B b=new B("b");
        C c=new C("c");
        System.out.println(a.name);
        System.out.println(b.name);
        System.out.println(c.name);
        c.speak();//C传递继承可以继承到A中的方法
        c.cry();//重写父类中的方法,如果没有继承就不能使用同样的方法名
        b.cry();
        a.cry();
    }
}

面向对象语言三大特征——封装、继承、多态

继承中的构造方法

子类构造方法会先调用父类构造方法

使用super关键字调用父类任意一个构造方法,必须写在构造方法的第一行

如果子类的构造方法中没有显式地调用基类构造方法,则系统默认调用基类无参数的构造方法

super关键字用途

使用super关键字访问父类成员

  • super.成员变量名来引用父类成员变量

  • super.方法名(参数列表)访问父类的方法。

  • super.构造方法(参数列表)访问父类构造方法。

    误区: 不要把super误认为是父类对象.在创建子类对象时,

    不会创建父类对象.

    只会将父类中的信息加载到子类对象中存储.

面向对象语言三大特征——封装、继承、多态

方法的重写(OverRide)

当父类的方法实现不能满足子类需求时,可以对方法进行重写( override)

在子类中可以根据需要对从基类(父类)中继承来的方法进行重写。

方法重写规则

方法名相同、参数列表相同

返回值类型相同

访问权限不能小于父类权限

<u>注意:构造方法, 静态方法不能重写,成员变量不存在重写

</u>

方法重载的定义

在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。

“两同一不同”

  • 同一个类、相同方法名

  • 参数列表不同:参数个数不同,参数类型不同

注:判断是否为重载,跟方法的权限修饰符、返回值类型、形参变量名、方法体都没有关系*

重写与重载区别

重载是定义相同的方法名,传入的参数不同。重写是子类重写父类中的方法。

重载是在一个类中。重写是发生在子类与父类之间。

重载是编译时的多态性(在编译时可以根据方法签名就判断出调用的什么方法)。重写是运行时的多态性(重写在编译时是无法看出使用的什么方法的)。

Java实现多态的三个必要条件:继承、方法重写、向上转型

有了对象的多态性之后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。

编译与运行

编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。

抽象类

抽象方法

抽象方法是一种特殊的方法:

它只有声明,而没有具体的实现.

抽象方法必须用abstract关键字进行修饰

抽象类的定义

  • 如果一个类中没有足够的信息来描绘一个具体的对象,这样的类就是抽象类。(包含抽象方法,有抽象方法的类一定是抽象类,但抽象类中不一定有抽象方法

  • 抽象类除了不能实例化对象以外,类的其他功能依然存在,成员变量成员方法构造方法

  • 用abstract修饰的类就是抽象类。如果某个类中包含有抽象方法,那么该类就必须定义成为抽象类。

抽象类的特点

抽象类不能被实例化,但可以有构造方法,因为抽象类中含有无具体实现的方法,所以不能用抽象类创建对象

抽象类只能用作基类,表示的是一种继承关系。继承抽象类的非抽象类必须是实现其中的所有抽象方法,而已实现方法的参数、返回值和抽象类中的方法一样。否则,该类也必须声明为抽象类。

使用关键字abstract定义抽象类,一般语法:

[访问权限] abstract class 类名 {

成员列表

}

public abstract class Shapes {

public abstract void draw();

}

public abstract class Shapes {

public void draw(){

//具体代码

}

}

abstract class Person {
    String name;
    String country;
    void say(){
        System.out.println("人说话");
    } 
}
class Chinese extends Person{
    public void say(){
        //重写抽象方法
        System.out.println("中国人说话");
    }
} 
public class Test {
    public static void main(String[] args) {
        Chinese c=new Chinese();
        System.out.println(c.name);
        c.say();
    }
}

面向对象语言三大特征——封装、继承、多态

多态

多态:同一种事物,在不同时刻表现不同的状态

多态存在的三个必要条件:

  • 要有继承(包括接口的实现)(前提条件)

  • 要有重写(前提条件)

  • 父类引用指向子类对象

public class Test{
      public static void main(String[] args){
      Dog xh=new Dog();
      /*
      编译期间 a.eat()  a的类型是Animal类,调用的是抽象的eat()
      运行期间 a指向的是一个Dog对象,运行的是Dog中重写的eat()    
      针对于非静态成员方法:
            编译期间看左边(写代码时)    运行期间看右边         */
      Animal a=new Dog();
      a.eat();//非静态成员方法(抽象方法)
      a.sleep();//sleep()为父类Animal(抽象类)中的非静态方法
      /* 
      针对静态方法:
             编译期间看左边      运行期间还是看左边     */
      a.play();//play()为父类(抽象类)中的静态方法
      /*     
      针对成员变量:
             编译期间看左边        运行期间还是看左边    */
      System.out.println(a.age);//age为父类中的成员变量
          //a为父类中的变量,因此成员变量只能调用父类中的
      }
}//父类为抽象类

主要还是看清就近关系!

多态调用成员方法:1.子类中重写父类的方法2.父类中本来就有的方法3.父类中的静态方法

多态直接输出成员变量:1.父类中的成员变量(没有就不能输出)

多态的用法

可以避免反复的调用而造成的繁琐。

public class Test3 {

    public static void main(String[] args) {

          Dog dog = new Dog();
          Cat cat = new Cat();
          Monkey monkey = new Monkey();

          Test3 t = new Test3();
          t.feedAnimal(dog);
          t.feedAnimal(cat);
          t.feedAnimal(monkey);

    }

    /*
       喂动物      将对象传入,调用动物中的方法
       判断animal中实际传入的类型是什么
       父类引用  instanceof 具体的子类类型
       instanceof 判断父类引用实际表示的对象  是不是 指定类型
     */
    public void feedAnimal(Animal animal){
        animal.eat();
       System.out.println(animal instanceof Dog);
        //判断传入的对象是否属于Dog类型,返回的是boolean类型
            if(animal instanceof Dog){
                Dog dog = (Dog)animal;
                dog.play();
            }
        
    }

多态转型

自动转型:

子 继承 父

向上类型:子类自动转型(上升型)为父类类型

Animal dog=new Dog();

强制转型:

向下转型:父类类型转为子类自己的类型(为了使用子类中特有的方法)

优点:父类引用表示子类对象,提升程序的扩展性

缺点:父类类不能调用子类中特有的方法

上一篇:面向对象的特征——多态


下一篇:面对对象(2)(类与对象的创建)