面对对象思想——三大特性

封装

概念:
利用抽象数据类型将数据和基于数据的操作封装,使其变成一不可分割独立实体。
特点:
数据于抽象数据类型内部被保护,隐藏内部细节,留对外接口与外界联系。用户无需关心对象内部细节,但可通过提供接口访问该对象。
优点:
①减少耦合:可独立开发、测试、优化、使用、理解和修改
②减轻维护负担:易理解,调试时不影响其他模块
③有效调节性能:可通过剖析确定哪些模块影响系统性能
④提高软件可重用性
⑤降低构造大型系统的风险:独立模块不受整体影响

public class Virus {

    private String name;
    private int type;
    private int time;

    public String getName() {
        return name;
    }

    public String getType() {
        return type == 0 ? "DNA" : "RNA";
    }

    public void alive() {
        if (3 <= time && age <= 24) {
            System.out.println(name + " maybe is 2019-nCoV!");
        } else {
            System.out.println(name + " can't alive any more!");
        }
    }
}

以上Virus类封装name、type、time等属性,外界只能通过get()方法获取name以及type属性,无法获取time属性,只能通过alive方法调用time。其中封装使得用户不知道属性使用的数据类型,且其不影响后续修改。

继承

概念:
实现is-A关系,如man和human的从属关系,man可以继承human,从而获得human非private的属性和方法
特点:
强耦合、破坏封装
原则:
里氏替换原则,子类对象必须能够替换掉所有父类对象
举例:
Human human = new Man();
关键:
构造器、protected关键字、向上转型
构造器
编译器会默认给子类调用父类的构造器(前提:父类有默认构造器;若无,用super()调用父类构造器)
protected关键字
对于protected而言,它指明就类用户而言,他是private,但是对于任何继承与此类的子类而言或者其他任何位于同一个包的类而言,他却是可以访问的
向上转型
将子类转换成父类,在继承关系上面是向上移动的,所以一般称之为向上转型。由于向上转型是从一个叫专用类型向较通用类型转换,所以它总是安全的,唯一发生变化的可能就是属性和方法的丢失。这就是为什么编译器在“未曾明确表示转型”活“未曾指定特殊标记”的情况下,仍然允许向上转型的原因

多态

分类:
编译时多态——方法的重载
运行时多态——程序中定义的对象引用所指向的具体类型在运行时才确定
条件:
继承、覆盖(重写)、向上转型
实现形式:
继承和接口
基于继承实现的多态——对于引用子类的父类类型,在处理该引用时,它适用于继承该父类的所有子类,子类对象的不同,对方法的实现也就不同,执行相同动作产生的行为也就不同。
接口的多态——指向接口的引用必须是指定这实现了该接口的一个类的实例程序,在运行时,根据对象引用的实际类型来执行对应的方法。
举例:
乐器类(Instrument)有两个子类:Wind 和 Percussion,它们都覆盖了父类的 play() 方法,并且在 main() 方法中使用父类 Instrument 来引用 Wind 和 Percussion 对象。在 Instrument 引用调用 play() 方法时,会执行实际引用对象所在类的 play() 方法,而不是 Instrument 类的方法。

public class Instrument {

    public void play() {
        System.out.println("Instument is playing...");
    }
}

public class Wind extends Instrument {

    public void play() {
        System.out.println("Wind is playing...");
    }
}

public class Percussion extends Instrument {

    public void play() {
        System.out.println("Percussion is playing...");
    }
}

public class Music {

    public static void main(String[] args) {
        List<Instrument> instruments = new ArrayList<>();
        instruments.add(new Wind());
        instruments.add(new Percussion());
        for(Instrument instrument : instruments) {
            instrument.play();
        }
    }
}

经典案例:

public class A {  
    public String show(D obj) {  
        return ("A and D");  
    }  
    public String show(A obj) {  
        return ("A and A");  
    }   
  }  
  
public class B extends A{  
    public String show(B obj){  
        return ("B and B");  
    }  
    public String show(A obj){  
        return ("B and A");  
    }   
}  
  
public class C extends B{ }  
  
public class D extends B{ }  
  
public class Test {  
    public static void main(String[] args) {  
        A a1 = new A();  
        A a2 = new B();  
        B b = new B();  
        C c = new C();  
        D d = new D();  
          
        System.out.println("1--" + a1.show(b));  
        System.out.println("2--" + a1.show(c));  
        System.out.println("3--" + a1.show(d));  
        System.out.println("4--" + a2.show(b));  
        System.out.println("5--" + a2.show(c));  
        System.out.println("6--" + a2.show(d));  
        System.out.println("7--" + b.show(b));  
        System.out.println("8--" + b.show(c));  
        System.out.println("9--" + b.show(d));        
    }  
}  

在这里插入图片描述
当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。
继承链中对象方法的调用存在一个优先级:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)
分析:
a2.show(b),a2是一个引用变量,类型为A,则this为a2,b是B的一个实例,于是它到类A里面找show(B obj)方法,没有找到,于是到A的super(超类)找,而A没有超类,因此转到第三优先级this.show((super)O),this仍然是a2,这里O为B,(super)O即(super)B即A,因此它到类A里面找show(A obj)的方法,类A有这个方法,但是由于a2引用的是类B的一个对象,B覆盖了A的show(A obj)方法,因此最终锁定到类B的show(A obj),输出为"B and A”。

参考资料:
面向对象编程三大特性------封装、继承、多态
cyc2018——面对对象思想

发布了8 篇原创文章 · 获赞 4 · 访问量 351

猜你喜欢

转载自blog.csdn.net/NobodyH/article/details/104291178