Java面向对象的三大特性:封装、继承、多态(详细讲解版)

一、 封装

1、概念

将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
举个例子:平时生活中用到的电脑,用户看不见内部实现的细节,只留一下接口给用户使用。

class Student{
    private String name;
    private int age;
} 

这里定义了一个学生类,类中的两个成员变量,用private(访问限定修饰符)修饰,让该成员方法只能在当前类中使用,不能在当前类外使用。

2、优点

  1. 安全:隐藏数据,防止被随意修改。
  2. 可控:通过方法操作数据,可以加入验证逻辑。
  3. 易维护:内部修改不影响外部调用。
  4. 简化使用:使用者无需了解内部复杂实现。
    总结:封装让代码更安全、更灵活、更容易维护。

二、继承

1、概念

继承(inheritance)机制:是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加新功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构, 体现了由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用
举个例子
Animal

public class Animal {
    public String name;
    public int age;
}

Cat类继承Animal类

public class Cat extends Animal{
    public void mew(){
        System.out.println(name+"喵喵....");
    }
}

Dog类继承Animal类

public class Dog extends Animal{
    public void bark(){
        System.out.println(name+"汪汪汪......");
    }
}

Test类

public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.name = "小黄";
        dog.age = 3;
        dog.bark();
        Cat cat = new Cat();
        cat.name = "小花";
        cat.age = 4;
        cat.mew();
    }
}

上面的Dog,Cat类==(子类/派生类)==继承了父类Animal类(父类/基类/超类),对它们的共性:名字和年龄进行抽取,实现了代码的复用。

建议的写法:一个java文件一个类
在这里插入图片描述

2、父类成员访问

2.1 子类中访问父类的成员变量

Base父类

public class Base {
   public int a = 1;
   public int b = 2;
}

Derived子类

public class Derived extends Base{
   public int c = 3;
    public int a = 100;
   public void func(){
       System.out.println("a="+this.a);
       System.out.println("b="+this.b);
       System.out.println("c="+this.c);
   }
}

Test测试类

public class Test {
    public static void main(String[] args) {
     Derived derived = new Derived();
     derived.func();
    }
}

此时父类和子类有同名成员变量 a,优先访问自己的。遵循就近原则,自己有优先自己的,如果没有则从父类中找。
打印结果
在这里插入图片描述

2.2 super关键字:在子类方法中访问父类的成员

Derived子类

public class Derived extends Base{
   public int c = 3;
    public int a = 100;
   public void func(){
   //在子类方法中访问父类的成员
       System.out.println("a="+super.a);
       System.out.println("b="+this.b);
       System.out.println("c="+this.c);
   }
}

打印结果
在这里插入图片描述
此时使用Java中的super关键字,成员变量a的值打印的就是父类中的1。

2.3 总结

在子类方法中 或者 通过子类对象访问成员时
1.如果访问的成员变量子类中有,优先访问自己的成员变量。
2.如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。
3.如果访问的成员变量与父类中成员变量同名,则优先访问自己的。
4.成员方法也遵循上面原则。
super关键字的注意事项:
1.只能在非静态方法中使用。
2. 在子类方法中,访问父类的成员变量和方法。

3、继承的优点

  1. 代码复用
    子类可以直接继承父类的属性和方法,无需重复编写相同的代码,提高了开发效率。

  2. 提高扩展性
    子类可以在继承的基础上,添加新的属性和方法,或者重写父类的方法,以适应新的需求,系统易于扩展。

  3. 便于维护
    当需要修改公共特性时,只需在父类中修改一次,所有子类都会自动继承这个修改,降低了维护成本和出错风险。

  4. 模拟现实世界关系
    继承能够很自然地描述现实世界中“是一种(is-a)”的关系(如:猫是一种动物),使模型更符合逻辑,易于理解。
    总结
    继承通过建立类之间的层次关系,实现了代码的高效复用、轻松扩展和集中维护。


三、多态

1、概念

通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。

2、多态实现的条件

在java中要实现多态,必须要满足以下条件,缺一不可。

  1. 必须在继承体系下
  2. 子类必须要对父类中方法进行重写
  3. 通过父类的引用调用重写的方法

2.1向上转型(补充)

概念:实际就是创建一个子类对象,将其当成父类对象来使用。
向上转型有三种方式:直接赋值,方法的传参,方法返回。
向上转型的优点:让代码实现更简单灵活。
向上转型的缺陷:不能调用到子类特有的方法。

2.1.1 直接赋值

Animal父类

public class Animal {
    public String name;
    public int age;

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void eat(){
        System.out.println("正在吃饭.....");
 }

Dog子类

public class Dog extends Animal{

   public Dog(String name, int age) {
       super(name, age);
   }
   public void bark(){
       System.out.println(this.name+"正在汪汪叫....");
   }
}

Test测试类

public class Test {
    public static void main(String[] args) {
        Animal animal = new Animal("旺财",7); //向上转型 父类引用 引用了子类对象

    }
}
2.1.2 方法的传参

Test测试类

public class Test {
    public static void func(Animal animal){
        
    }
    public static void main(String[] args) {
        Dog dog = new Dog("小黄",4);
        func(dog);
    }
}
2.1.2 方法返回

Test测试类

public class Test {
    public static Animal func(){
        Dog dog = new Dog("小黄",4);
        return dog;
    }
    public static void main(String[] args) {
        Animal animal = func();
    }
}

2.2动态绑定(理解多态的基础)

前提:一定要在继承的情况下
1.父类引用 引用了子类对象。
2.通过父类的引用调用了父类和子类重写的那个方法。
Animal父类

public class Animal {
    public String name;
    public int age;

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void eat(){
        System.out.println("正在吃饭.....");
    }
}

Dog子类

public class Dog extends Animal{

   public Dog(String name, int age) {
       super(name, age);
   }
   public void bark(){
       System.out.println(this.name+"正在汪汪叫....");
   }
   @Override
   public void eat(){
       System.out.println("狗狗正在吃狗粮.....");
   }
}

Test测试类

public class Test {
    public static Animal func(){
        Dog dog = new Dog("小黄",4);
        return dog;
    }
    public static void main(String[] args) {
        Animal animal = func();
        animal.eat();
    }
}

打印结果
在这里插入图片描述
这里我们发现打印的结果是Dog子类eat()方法中的“狗狗正在吃狗粮…” ,是因为这里发生了动态绑定。编译的时候调用的确实是父类的eat()方法,当代码运行的时候,通过父类的引用调用了父类和子类重写的eat()方法结果实际调用了Dog子类eat()方法。

2、多态代码例子讲解

Animal父类

public class Animal {
    public String name;
    public int age;

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void eat(){
        System.out.println("正在吃饭.....");
    }
}

Dog子类

public class Dog extends Animal{

   public Dog(String name, int age) {
       super(name, age);
   }
   public void bark(){
       System.out.println(this.name+"正在汪汪叫....");
   }
   @Override
   public void eat(){
       System.out.println("狗狗正在吃狗粮.....");
   }
}

Bird子类

public class Bird extends Animal{

    public Bird(String name, int age) {
        super(name, age);
    }
    public void fly(){
        System.out.println(this.name+"正在飞....");
    }
    @Override
    public void eat(){
        System.out.println("鸟儿正在吃虫子.....");

}
}

Test测试类

public class Test {
    public static void func(Animal animal){
        animal.eat();
    }
    public static void main(String[] args) {
       Dog dog = new Dog("旺财",3);
       func(dog);
        System.out.println("=================");
        Bird bird = new Bird("小鸟",2);
        func(bird);
    }
}

打印结果
在这里插入图片描述

这里我们写了两个子类 Dog 和Bird,两个类都重写了Animal父类的eat()方法。在Test类中animal引用的对象不一样,但是调用的是同一个方法(eat()方法),此时表现出的现象不一样,这种思想就叫做多态

3、多态的优缺点

3.1优点

  1. 能够降低代码的 “圈复杂度”(一种描述一段代码复杂程度的方式), 避免使用大量的 if - else。
  2. 可扩展能力更强。

3.2缺点

1.代码的运行效率降低。
2.属性没有多态性,当父类和子类都有同名属性的时候,通过父类引用,只能引用父类自己的成员属性。
3.构造方法没有多态性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值