前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java基础-封装、继承、多态

Java基础-封装、继承、多态

作者头像
越陌度阡
发布2024-05-24 15:07:08
640
发布2024-05-24 15:07:08
举报

Java是一门面向对象非常好的语言,拥有面向对象的三个基本特征:封装、继承、多态。

1. 什么是封装?

封装就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。

1.1. 封装的规则

1. 将类的某些信息隐藏在类的内部,不允许外部程序直接访问;

2. 通过该提供的方法来实现对隐藏信息的操作和访问;

1.2. 封装的步骤

1. 修改属性为私有设为private;

2. 创建getter和setter方法,设为public用于属性的读写;

3. 在gettter和setter方法中加入属性控制语句,用于对属性的合法进行判断;

1.3. 封装的实现

1. 封装一个学生类

代码语言:javascript
复制
public class Student {

    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;
    }

    // 无参构造函数
    public Student(){


    }

    // 有参构造函数
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

}

2. 调用学生类实例化对象

代码语言:javascript
复制
public class StudentTest {
    public static void main(String[] args){
        // 实例化一学生
        Student student = new Student();
        // 设置学生姓名
        student.setName("aiguangyuan");
        // 设置学生年龄
        student.setAge(30);
    }
}

2. 什么是继承?

继承是面向对象的三大特性之一,可以使子类具有父类的属性和方法,还可以在子类中重新定义、追加属性和方法。当多个类中存在相同的属性和方法,使用继承模式将每个子类相同代码直接抽取出来放到父类中。

2.1. 继承的相关概念及实现

1. 父类:也被称为基类、超类

代码语言:javascript
复制
package aiguangyuan.test;

public class Parent {

    protected   String name;
    protected   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;
    }
}

2. 子类:也被称为派生类

代码语言:javascript
复制
package aiguangyuan.test;

public class Son extends Parent{
    public void  work(){
        System.out.println("我是"+this.name+",今年"+this.age+"岁,我正在写代码");
    }
}

3. 写一个类进行测试

代码语言:javascript
复制
package aiguangyuan.test;

public class Test {

    public static void main(String[] args) {

        Son son = new Son();

        son.setAge(20);
        son.setName("Mark");

        int age = son.getAge();
        String name = son.getName();

        System.out.println(age);
        // 20
        System.out.println(name);
        // Mark
        son.work();
        // 我是Mark,今年20岁,我正在写代码

    }
}
2.2. 继承的优缺点

1. 继承的优点

提高了代码的复用性,多个类相同的成员属性和方法可以放到一类中;

提高了代码的复用性,如果方法的代码需要修改,只需修改一处即可;

2. 继承的缺点;

继承让类与类之间产生了关系,类的耦合性也增加了,当父类发生变化时,子类也不得不跟着变化,削弱了子类的独立性;

2.3. 继承中变量的访问规则

1. 首先在子类局部范围中查找;

代码语言:javascript
复制
package aiguangyuan.test;
public class Son extends Parent{
    public int age = 20;
    public void show(){
         int age = 22;
         System.out.println("当前的年龄为:"+age);
         // 当前的年龄为:22
    }
}

2. 如果子类局部范围中查找没有,就在子类成员范围查找;

代码语言:javascript
复制
package aiguangyuan.test;
public class Son extends Parent{
    public int age = 20;
    public void show(){
         // int age = 22;
         System.out.println("当前的年龄为:"+age);
         // 当前的年龄为:20
    }
}

3. 如果在子类局部范围和子类成员范围查找都没有,就在父类成员查找;

父类代码:

代码语言:javascript
复制
package aiguangyuan.test;
public class Parent {
    public  int age = 18;
    public  int height = 175;
    public  int weight = 120;
}

子类代码:

代码语言:javascript
复制
package aiguangyuan.test;
public class Son extends Parent{
    // public int age = 20;
    public void show(){
         // int age = 22;
         System.out.println("当前的年龄为:"+age);
         // 当前的年龄为:18
    }
}

4. 子类局部范围中访问子类成员范围使用this;

代码语言:javascript
复制
package aiguangyuan.test;
public class Son extends Parent{
    public int age = 20;
    public void show(){
         int age = 22;
         System.out.println("当前的年龄为:"+this.age);
         // 当前的年龄为:20
    }
}

5. 子类局部范围中访问父类成员范围使用super;

父类代码:

代码语言:javascript
复制
package aiguangyuan.test;
public class Parent {
    public  int age = 18;
    public  int height = 175;
    public  int weight = 120;
}

子类中使用父类成员:

代码语言:javascript
复制
package aiguangyuan.test;
public class Son extends Parent{
    public int age = 20;
    public void show(){
         int age = 22;
         System.out.println("当前的年龄为:"+super.age);
         // 当前的年龄为:18
    }
}
2.4. 继承中构造方法的访问规则

子类中所有的构造方法默认都会访问父类中的无参构造方法。

因为子类会继承父类中的数据,所以子类初始化之前,需要对父类进行初始化。

每个子类构造方法的第一句默认都是super()。

如果父类中没有无参构造方法,只有带参构造方法,怎么办?

1. 父类中自己单独定义一个无参构造方法;

2. 通过super关键字显示调用父类的有参构造方法;

父类如下:

代码语言:javascript
复制
package aiguangyuan.temp;
public class Parent {
    // 父类中没有无参构造方法
    public Parent(int age){
        System.out.println("父类中的有参构造方法,参数为:"+age);
    }
}

子类如下:

代码语言:javascript
复制
package aiguangyuan.temp;
public class Son extends Parent{
    public Son(){
        // 父类中没有无参构造函数,通过super调用父类有参构造函数
        super(48);
        System.out.println("儿子类的无参构造方法");
    }
    public Son(int age){
        // 父类中没有无参构造函数,通过super调用父类有参构造函数
        super(48);
        System.out.println("儿子类的有参构造方法,参数为:"+age);
    }
}
2.5. 继承中的成员方法访问规则

1. 首先在子类范围中查找;

代码语言:javascript
复制
package aiguangyuan.study;
public class Son extends Parent {
    public void study(){
        System.out.println("我是儿子,我很热爱学习");
    }
}

以上是一个儿子类,他继承了父类,里面有一个study方法。

代码语言:javascript
复制
package aiguangyuan.study;
public class Test {
    public static void main(String[] args) {
        Son son = new Son();
        son.study();
        // 我是儿子,我很热爱学习
    }
}

当实例化儿子对象时,调用study方法,首先调用儿子类里面的study方法。

2. 如果在子类中查找没有,就在父类成员查找;

父类如下:

代码语言:javascript
复制
package aiguangyuan.study;
public class Parent {
    public void study(){
        System.out.println("我是父亲,我很热爱学习");
    }
}

子类如下:

代码语言:javascript
复制
package aiguangyuan.study;
public class Son extends Parent {
    
}

结果如下:

代码语言:javascript
复制
package aiguangyuan.study;
public class Test {
    public static void main(String[] args) {
        Son son = new Son();
        son.study();
        // 我是父亲,我很热爱学习
    }
}

3. 如果父类和子类中都没有则会报错;

2.6. 继承中访问关键字的总结

1. this代表本类对象的引用;

2. super代表父类存储空间的标识,可以理解为父类对象的引用;

2.7. 继承中的方法覆写

当子类中出现了和父类一模一样的方法,该方法中需要父类的功能,而又有自己独特的内容,这样就可以通过覆写父类的方法,这样既延续了父类的功能,又定义了自己的内容。

父类如下:

代码语言:javascript
复制
package aiguangyuan.temp;
public class Phone {
    public  void call(String name){
        System.out.println(name+"手机可以拨打电话");
    }
}

子类如下:

代码语言:javascript
复制
package aiguangyuan.temp;
public class NewPhone extends Phone{
    @Override // 此注解代表覆写
    public  void  call(String name){
        System.out.println("华为手机支持视频通话");
        super.call(name);
    }
}

结果如下:

代码语言:javascript
复制
package aiguangyuan.temp;
public class TestPhone {
    public static void main(String[] args) {
        NewPhone newPhone = new NewPhone();
        newPhone.call("诺基亚");
        // 华为手机支持视频通话
        // 诺基亚手机可以拨打电话
    }

}

方法重写注意事项:

1. 私有的方法不能被重写,因为父类中的私有方法子类不能被继承;

2. 子类方法访问权限不能比父类低,可以大于也可以等于,其中公有大于默认,默认大于私有;

2.8. 继承中的权限修饰符

Java中有四种权限修饰符,其中三种有访问权限修饰符,分别为private、public和protected,还有一种不带任何修饰符。

1. private:Java语言中对访问权限限制最窄的修饰符,一般称之为私有的。被其修饰的的类、属性及方法只能被该类的对象访问,其子类不能访问,更不允许跨包访问;

2. default:即不加任何访问修饰符,通常称为默认访问模式。该模式下,只允许在同一个包中进行访问;

3. protect:介于public和private之间的一种访问修饰符,一般称之为保护模式。被其修饰的类、属性及方法只能被类本身的方法及子类访问,即使子类在不同的包中也可以访问;

4. public:Java中访问限制最宽的修饰符,一般称之为公有的。被其修饰的类、属性及方法不仅可以跨类该问,还可以跨包访问;

2.9. 多层继承

在C++语言中,是可以同时继承两个父类的,但是在Java中只支持单继承,如果要继承两个父类,需要分两次分别继承,即多层继承。

3. 什么是多态?

多态是面向对象的三大特征之一,即同一个对象,在不同的时刻表现出来不同的形态。

3.1. 多态的前提和实现

1. 有继承或实现的关系;

2. 子类有对父类的方法进行重写;

3. 父类的引用来自子类对象;

父类代码:

代码语言:javascript
复制
package aiguangyuan.temp;
public class AnimalParent {
    public  void  eat(){
        System.out.println("这是动物父类中的吃方法");
    }
}

子类代码:

代码语言:javascript
复制
package aiguangyuan.temp;
public class Dog  extends AnimalParent{
    @Override
    public void  eat(){
        System.out.println("狗类重写了父类的吃方法");
    }
}

多态实现:

代码语言:javascript
复制
package aiguangyuan.temp;

public class AnimalDemo {
    public static void main(String[] args) {

        // 子类的引用来自子类
        // Dog dog = new Dog();
        // dog.eat();

        // 父类的引用来自子类
        AnimalParent animalParent = new Dog();
        animalParent.eat();
        // 狗类重写了父类的吃方法
    }
}
3.2. 多态的访问特点

成员变量:编译看左边,执行看左边;

成员方法:编译看左边,执行看右边;

为什么成员变量和成员方法的访问不一样呢?

这是因为成员方法有重写,而成员变量是没有的。

父类代码:

代码语言:javascript
复制
package aiguangyuan.test;
public class AnimalParent {
    public int age = 40;
    public  void  eat(){
        System.out.println("我是动物父类中的吃方法");
    }
}

子类代码:

代码语言:javascript
复制
package aiguangyuan.test;
public class Dog extends AnimalParent{
    public int age = 20;
    public  int weight = 40;
    @Override
    public void eat() {
        System.out.println("我是狗类中的吃方法");
    }

    public  void  show(){
        System.out.println("当前显示的是狗类");
    }
}

执行示例:

代码语言:javascript
复制
package aiguangyuan.test;
public class AnimalDemo {
    public static void main(String[] args) {

        AnimalParent animalParent = new Dog();

        // System.out.println(animalParent.weight);
        // 编译报错,因为左边的animalParent没有wight属性,所以也无法执行

        // animalParent.show();
        // 编译报错,因为左边的animalParent没有show方法

        animalParent.eat();
        // 执行成功,因为右边的Dog类中有eat方法
    }
}
3.3. 多态的访问优点和缺点

多态的好处:提高了程序的扩展性。

具体的体现:定义方法的时候,使用父类型作为参数,将来在使用的时候,使用具体的子类型参操作。

定义动物父类:

代码语言:javascript
复制
package aiguangyuan.test;
public class AnimalParent {
    public  void  eat(){
        System.out.println("我是动物父类中的吃方法");
    }
}

定义子类的狗类:

代码语言:javascript
复制
package aiguangyuan.test;
public class Dog extends AnimalParent{
    @Override
    public void eat() {
        System.out.println("我是狗类,我在吃屎");
    }
}

定义子类的猫类:

代码语言:javascript
复制
package aiguangyuan.test;
public class Cat extends AnimalParent{
    @Override
    public void eat() {
        System.out.println("我是猫类,我在吃鱼");
    }
}

定义动物的操作类:

代码语言:javascript
复制
package aiguangyuan.test;

public class AnimalOperate {

    //public  void  useCatEat(Cat cat){
    //    cat.eat();
    //}
    //public  void  useDogEat(Dog dog){
    //    dog.eat();
    //}
    //

    // 定义方法的时候,使用父类型作为参数,
    public  void  useAnimal(AnimalParent animalParent){
        animalParent.eat();
    }
    
}

执行示例:

代码语言:javascript
复制
package aiguangyuan.test;

public class AnimalDemo {
    public static void main(String[] args) {

        // 调用动物操作类
        AnimalOperate animalOperate = new AnimalOperate();


        // 调用猫类中的useCatEat方法
        //animalOperate.useCatEat(new Cat());
        // 我是猫类,我在吃鱼

        // 调用狗类中的useDogEat方法
        //animalOperate.useDogEat(new Dog());
        // 我是狗类,我在吃屎


        // 在使用的时候,使用具体的子类型参操作。

        animalOperate.useAnimal(new Cat());
        // 我是猫类,我在吃鱼
        animalOperate.useAnimal(new Dog());
        // 我是狗类,我在吃屎

        
    }
}

多态的弊端:不能使用子类的特有功能。

3.4. 多态中的转型

1. 向上转型,从子类到父类,父类引用指向子类对象,也是Java中默认的存在方式;

2. 向下转型,从父类到子类,父类引用转为子类对象,这种方式只能显示的强转;

定义父类:

代码语言:javascript
复制
package aiguangyuan.test;
public class AnimalParent {
    public  void  eat(){
        System.out.println("我是动物父类中的吃方法");
    }
}

定义子类狗类:

代码语言:javascript
复制
package aiguangyuan.test;
public class Dog extends AnimalParent{
    @Override
    public void eat() {
        System.out.println("我是狗类,我在吃屎");
    }
    public void showDog(){
        System.out.println("我是小狗");
    }
}

执行示例:

代码语言:javascript
复制
package aiguangyuan.test;

public class AnimalDemo {
    public static void main(String[] args) {

        Dog dog1 = new Dog();
        dog1.showDog();
        // 我是小狗

        // 多态中,编译阶段是看左边,执行是看右边,向上转型,从子到父
        AnimalParent parent = new Dog();

        // parent中没有showDog方法,如果想调用该方法需要向下转型,从父到子
        Dog dog2 = (Dog) parent;
        dog2.showDog();
        // 我是小狗

    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-05-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 什么是封装?
    • 1.1. 封装的规则
      • 1.2. 封装的步骤
        • 1.3. 封装的实现
        • 2. 什么是继承?
          • 2.1. 继承的相关概念及实现
            • 2.2. 继承的优缺点
              • 2.3. 继承中变量的访问规则
                • 2.4. 继承中构造方法的访问规则
                  • 2.5. 继承中的成员方法访问规则
                    • 2.6. 继承中访问关键字的总结
                      • 2.7. 继承中的方法覆写
                        • 2.8. 继承中的权限修饰符
                          • 2.9. 多层继承
                          • 3. 什么是多态?
                            • 3.1. 多态的前提和实现
                              • 3.2. 多态的访问特点
                                • 3.3. 多态的访问优点和缺点
                                  • 3.4. 多态中的转型
                                  领券
                                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档