JAVA面向对象--封装继承和多态

本文介绍了封装、继承和多态三种面向对象编程的基本概念,包括封装如何提高代码安全性和复用性,继承如何实现代码复用和维护,以及多态如何增强代码扩展性和灵活性。通过实例展示了如何在Java中运用这些概念。
摘要由CSDN通过智能技术生成

一、封装

1.什么是封装?

封装是指把一个对象的属性隐藏在对象内部,不允许外部对象直接访问对象的内部信息。但是可以提供一些可以被外界访问的方法来操作属性。

2.为什么要使用封装?

public class Student {
    public String name;
    public Integer Id;

    public Student() {
    }

    public Student(String name, Integer id) {
        this.name = name;
        Id = id;
    }
}

现有一个Student类,其中的所有属性都是公开的,那也就意味着我们可以随意访问或修改类中的属性值

public class Test1 {
    public static void main(String[] args) {
        Student student = new Student("Tome",1);
        System.out.println(student.Id);
        student.Id = -20;
        System.out.println(student.Id);
    }
}

这些属性值不是说不能修改,即使一定要修改,也要在合适的规则下修改,上面代码中将学生Id设置为负数,很明显是不符合逻辑的。

要解决这个问题,首先需要将属性变为私有,不允许外部直接访问,然后提供对应的set,get方法允许外界操作属性。就像这样:

public class Student {
    private String name;
    private Integer Id;

    public Student() {
    }


    public String getName() {
        return name;
    }

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

    public Integer getId() {
        return Id;
    }

    public void setId(Integer id) {
        if (id>0){
            Id = id;    
        }else {
            System.out.println("输入的Id不合法,请重新输入");
        }
    }
}

外界想要访问属性值就需要这样:

public class Test1 {
    public static void main(String[] args) {
        Student student = new Student();
        student.setName("Tom");
        student.setId(3);
        System.out.println(student.getName() + "***" + student.getId());
        //如果直接访问name或Id就会报错
//        student.name="Jack";
//        student.Id=5;
    }
}

3.封装的好处

首先,它提高了代码的安全性,它在属性被访问前增加了一个屏障,使得使用者需要在合理的范围内访问和修改属性值,而不是随意修改;其次,它还增强了代码的复用性,今天我封装了一个学生类,以后创建学生对象时都可以使用这个类,无需再次编写学生类的代码。

二、继承

1.什么是继承?

不同类型的对象,相互间经常有一定数量的共同点。比如不同职业的人,他们都属于人类;不同种类的动物,他们都属于动物类;不同品牌的衣服,它们都属于服装类。将这些不同对象中的共有属性和共有方法抽取出来,就可以组成他们的父类。

2.为什么要使用继承?

public class Phone {
    private String brandName;
    private Integer price;

    public Phone() {
    }

    public void call(){
        System.out.println("打电话");
    }

    public void text(){
        System.out.println("发短信");
    }

    public String getBrandName() {
        return brandName;
    }

    public void setBrandName(String brandName) {
        this.brandName = brandName;
    }

    public Integer getPrice() {
        return price;
    }

    public void setPrice(Integer price) {
        this.price = price;
    }

}
public class HuaWei extends Phone {
    private String version;

    public HuaWei() {
        super();
    }

    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    @Override
    public void call() {
        System.out.println(super.getPrice() + "的" + super.getBrandName() + this.version + "打电话");
    }

    @Override
    public void text() {
        System.out.println(super.getPrice() + "的" + super.getBrandName() + this.version + "发短信");
    }
}
public class iPhone extends Phone {
    private String version;

    public iPhone() {
        super();
    }

    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    @Override
    public void call() {
        System.out.println(super.getPrice() + "的" + super.getBrandName() + this.version + "打电话");
    }

    @Override
    public void text() {
        System.out.println(super.getPrice() + "的" + super.getBrandName() + this.version + "发短信");
    }
}

上面的代码中,手机类定义了品牌名称和价格两个属性及其set和get方法,所以它的两个子类就无需重复定义这两个属性了及其方法了,当然,子类也可以有自己的特有属性和方法,比如上面的version属性及其set,get方法。

另外,手机类中还定义了call和text方法,如果这些父类自定义的方法可以满足子类的功能需求,那么子类能拿过来直接用,如果不能的话,子类可以重写父类的方法。

通过以上代码还可以看出super关键字指向父类存储空间,this关键字指向子类存储空间。子类想调用父类构造方法需要通过super()调用,访问父类成员变量和方法时需要通过“super.”的形式,访问本类成员变量和方法还是通过“this.”的形式。

public class Test1 {
    public static void main(String[] args) {
        HuaWei huaWei = new HuaWei();
        huaWei.setBrandName("华为");
        huaWei.setPrice(7999);
        huaWei.setVersion("mate60");
        huaWei.call();
        huaWei.text();

        iPhone iPhone = new iPhone();
        iPhone.setBrandName("苹果");
        iPhone.setPrice(8999);
        iPhone.setVersion("iPhone15");
        iPhone.call();
        iPhone.text();
    }
}

通过上面的代码就可以控制子类的属性和方法输出结果了。

3.继承的好处

  • 继承提高了代码的复用性,父类中定义过得属性和方法,子类可以直接拿来用,无需重复定义
  • 继承提高了代码的可维护性,父类中某个方法出现bug,只需要修改父类的方法逻辑就可以了,子类无论是否重写了这个方法都不会受到影响
  • 继承让类与类之间产生了关系,为多态提供了前提条件

三、多态

1.什么是多态?

多态就是一个对象具有的多种状态,具体表现为父类引用指向子类实例。

public class Test1 {
    public static void main(String[] args) {
        // 当前事物, 是一只猫
        Cat c = new Cat();
        c.eat();
        // 当前事物, 是一只动物
        Animal a = new Cat();
        a.eat();

    }
}

class Animal {
    public void eat(){
        System.out.println("动物吃饭");
    }
}

class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

多态的三个必要条件:

  • 要有继承关系
  • 子类要重写父类的方法
  • 要有父类引用指向子类对象

2.为什么要使用多态?

为了让一个父类型变量引用不同的子类对象,从而使具体的方法逻辑随着子类对象的改变而改变。

下面的代码简单定义了一个Animal类,并用Cat类和Dog类继承它。另外定义了一个方法useAnimal,形参为Animal对象,当传入参数为Animal的子类对象时,这个方法会自动调用不同对象对应的eat方法。

public class Test2 {
    public static void main(String[] args) {
        //这里就是根据传入对象的不同改变方法的执行逻辑
        useAnimal(new Cat());
        System.out.println("-------------------");//分隔符

        useAnimal(new Dog());
        System.out.println("-------------------");

        //向上转型:
        Animal a1 = new Dog();
        a1.eat();//这里执行Dog类的成员方法,因为对于成员方法来说,编译看父类,运行看子类
        a1.drink();//由于子类无法重写父类静态方法,所以这个静态方法执行的还是父类的,等同于Animal.drink()
        System.out.println(a1.i);//这里打印的还是10,因为对于成员变量来说,编译和运行都看父类。
        System.out.println("-------------------");

        Animal a2 = new Cat();
        //向下转型:
        Cat cat = (Cat) a2;
        cat.catchMouse();
    }

    public static void useAnimal(Animal animal){//这里传入的参数如果是子类对象,就默认发生了向上转型
        animal.eat();
        System.out.println(animal.i);

        //在这个方法中调用Cat特有的方法就需要判断传入的对象是不是Cat类型
        if (animal instanceof Cat c){
            c.catchMouse();
        }
    }
}

class Animal{
    int i = 10;
    public void eat(){
        System.out.println("Animal eat...");
    }

    public static void drink(){     //子类不能重写父类的静态方法
        System.out.println("Animal drink...");
    }
}

class Cat extends Animal{
    int i = 20;

    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }

    public void catchMouse(){
        System.out.println("猫抓老鼠");
    }
}

class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println("狗吃肉");
    }

    public static void drink(){
        System.out.println("狗喝水");
    }
}

总结起来有这么几点:

  1. 通过多态可以调用到父类被子类重写的成员方法(编译时看父类,运行时看子类),但只能调用到父类的成员变量(编译时看父类,运行时也看父类)
  2. 子类特有的成员变量和成员方法无法通过多态调用,只能实例化对象再调用
  3. 父类的静态方法无法被子类重写,即使子类以定义了与父类一模一样的静态方法,通过多态也只能调用到父类的静态方法
  4. 如果一个方法的形参是父类对象,那么要想在这个方法中调用某个子类(比如上面代码中的Cat类)的特有方法,就必须用instanceof关键字判断实参是不是这个类的实例对象,是的话才能调用

3.多态的好处

多态的好处在于增强了代码的扩展性和灵活性,通过传入同一类型的父类对象,执行不同子类的方法逻辑,无需根据形参是父类对象还是子类对象定义不同的方法,某种程度上也提高了开发效率。

  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java作为一种面向对象的编程语言,具有封装继承多态这三个重要概念。 首先,封装是指将数据和对数据的操作封装在一个类中,隐藏了实现的细节。通过封装,我们可以将数据的访问权限进行控制,从而保证数据的安全性和完整性。通过提供公共方法,我们可以控制对象对数据的访问方式,使得使用者只能通过指定的方法来访问和修改数据,避免了不恰当的操作。 其次,继承是指子类可以继承父类的属性和方法,可以实现代码的复用。通过继承,我们可以建立类之间的层次关系,并且在子类中可以重写父类的方法,实现对方法的扩展和改进。继承还可以提高代码的可维护性和可扩展性,当需要修改或新增功能时,只需要在相应的子类中进行修改或扩展,而不需要修改所有的类。 最后,多态是指同一个方法可以根据不同的对象产生不同的行为。多态性可以提高代码的灵活性和可扩展性,使代码更易于理解和维护。通过多态,我们可以对不同对象使用相同的方法和接口,使得代码的逻辑更清晰,减少条件判断和重复的代码。 综上所述,封装继承多态Java面向对象编程中的重要概念。封装可以保证数据的安全性和完整性,继承可以实现代码的复用和功能的扩展,多态可以提高代码的灵活性和可扩展性。掌握这三个概念,可以帮助我们更好地设计和实现面向对象的程序,提高代码的质量和效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值