Java面向对象三大特征的理解

面向对象三大特征的理解

初始理解

其实这些知识很早就有接触,而且一些概念也牢记于心了。自己叙述面向对象的特征会是这样的:
面向对象的三大特征是封装、继承和多态。封装是对代码的封装以实现迪内聚高耦合的设计,使代码更安全且具有良好的扩展性。继承是父类产生子类的过程,子类可以使用父类的非私有的属性和方法。多态是一个对象在不同时刻可以表现出不同状态的现象。外加Animal和Cat的例子。
这一段时间敲了不少的Java代码,在敲代码的过程中想了无数次的面向对象这几个概念,对他们有了更深的了解,在这里分享一下。

封装

封装确实是对代码的封装,但是只是这样理解却又太肤浅了,至少结合Java来思考一下里面的封装嘛。
不知道大家有没有想过我们在写JavaBean的时候为什么要将属性的权限修饰为private,其实是为了使我们的代码更安全。分析如下:

public class Cat {
    //这里通过private修饰属性,外界访问属性需要通过getter和setter方法
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    //假设我们设置age,如果用户恶意将age设置为100
    //众所周知,impossible,因此我们可以通过setter方法进行if判断然后再赋值
    public void setAge(int age) {
        this.age = age;
    }
}
我们可以考虑一下如果没有setter方法的判断,我们将该类的属性设置为public呢?那么用户的恶意输入,怎样规避呢?
总之:private是封装的一种体现。

封装还有其他的方法:为了提高代码的复用性可以将公共逻辑抽取成方法,将公共属性抽取成类。例如我们在不同的位置用到了相同的for循环,在idea中我们就可以选中相同的for循环部分,点击快捷键 ctrl + alt + m 将其抽取为方法。

继承

继承是面向对象的三大特征之一,过程就是使子类获得父类的属性和方法。
这个过程较容易理解,关键字是extends,如果我们定义的类没有显式继承某个类,系统默认为我们继承Objects。继承是我们代码的coding量变少了,提高了代码的复用性。
这里更深的体会是继承提高了代码的维护性。主要表现就是如果方法的代码需要修改,某些情况下我们只需要修改一处就可以实现。
但是这里还有一点没有想通的继承肯定会增加代码的耦合性,我们为什么还要这样夸大继承呢?我有这种疑问就是陷入了一个思维的误区,可以看这篇文章来解疑:为耦合辩护,为继承伸冤

多态

多态的三个必要条件是:

  1. 有继承或实现关系
  2. 有方法的重写
  3. 父类引用指向子类对象
class Fu {
    int num = 10;
    public void method(){
        System.out.println("Fu.. method");
    }
}
class Zi extends Fu {
    int num = 20;
    public void method(){
        System.out.println("Zi.. method");
    }
}
public class Test2Polymorpic {
    public static void main(String[] args) {
        Fu f = new Zi();
        System.out.println(f.num);
        f.method();
    }
}

关于为什么访问成员变量和成员方法的会分别get父类和子类的值和方法,这里有讲解。从虚拟机角度看Java多态->(重写override)的实现原理

  1. 好处:提高程序的扩展性。定义方法时候,使用父类型作为参数,在使用的时候,使用具体的子类型参与操作
  2. 弊端:不能使用子类的特有成员
    解决弊端可以通过向下转型:格式为子类型 对象名 = (子类型)父类引用;
class Fu {
    public void show(){
        System.out.println("Fu..show...");
    }
}
class Zi extends Fu {
    @Override
    public void show() {
        System.out.println("Zi..show...");
    }
    public void method(){
        System.out.println("我是子类特有的方法, method");
    }
}
public class Test {
    public static void main(String[] args) {
        //向上转型 : 父类引用指向子类对象
        Fu f = new Zi();
        f.show();
        // 多态的弊端: 不能调用子类特有的成员
        // f.method();
        //解决方法:
        // A: 直接创建子类对象
        // B: 向下转型
        //向下转型 : 从父类类型, 转换回子类类型
        Zi z = (Zi) f;
        z.method();
    }
}

如果被转的引用类型变量,对应的实际类型和目标类型不是同一种类型,那么在转换的时候就会出现ClassCastException,可以使用instanceOf来解决。

abstract class Animal {
    public abstract void eat();
}

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

    public void watchHome(){
        System.out.println("看家");
    }
}

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

public class Test4Polymorpic {
    public static void main(String[] args) {
        useAnimal(new Dog());
        useAnimal(new Cat());
    }

    public static void useAnimal(Animal a){
        a.eat();
        // 判断a变量记录的类型, 是否是Dog
        if(a instanceof Dog){
            Dog dog = (Dog) a;
            dog.watchHome();
        }
    }

}

最后再来一张图体会一下多态的强大:::::
equals的参数可以是任意对象类型,这是多态的一种应用

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章