面向对象的三大特征
继承、封装、多态
接口(Interface)是用来定义行为的!
抽象类(Abstract Class)是用来实现行为的!
具体类(Class)是用来执行行为的!
使用了对象就叫基于对象,基于对象的基础上增加了继承从而变成了面向对象。
封装
是对象和类概念的主要特征
封装:即把客观事物封装成抽象的类,并且类可以对自己的数据和方法进行权限控制,
封装就是指利用抽象数据类型将数据和基于数据的操作封装在一起,数据被保护在抽象类型的内部,系统的其他部分只有通过包裹在数据外面的被授权的操作,才能够与这个抽象数据类型交流与交互!
封装的优点
将变化隔离
便于使用
提高安全性
提高重用性
总结
封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据。对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法。
继承
继承:
继承是使用已存在的类的定义作为基础建立新的类,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承我们能够非常方便地复用以前的代码,能够大大的提高开发的效率。
继承的特点:
子类拥有父类非private的属性和方法。
子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
子类可以用自己的方式实现父类的方法。(重写)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 Father父类 class Father { public String name; private int money; public Father () { this .name = "李明" ; this .money = 1000 ; } public String getName () { return name; } public Father setName (String name) { this .name = name; return this ; } public int getMoney () { return money; } public Father setMoney (int money) { this .money = money; return this ; } public void say () { System.out.println("我是父亲" ); } public void speak () { System.out.println("父亲是我" ); } } 子类Son继承父类Father class Son extends Father { public String sonName; public Son () { this .sonName = "李小明" ; } @Override public void say () { System.out.println("我的父亲是:" +name+"他的存款我不知道..." ); System.out.println("我的父亲是:" +getName()+"但他的存折显示存款为:" +getMoney()); } public void speak (int age) { System.out.println("我的名字是:" +sonName+",年龄:" +age); } } public class Test { public static void main (String[] args) { Son s = new Son(); s.say(); s.speak(20 ); } }
执行结果:
1 2 3 我的父亲是:李明,他的存款我不知道... 我的父亲是:李明,但他的存折显示存款为:1000 我的名字是:李小明,年龄:20
栗子分析:
父类Father有自己的公有属性name
,私有属性money
,同时对外提供了所有属性的公有方法(get/set)
子类Son继承父类Father后,拥有父类所有非private的属性和方法的访问权限,子类Son同时还可以有自己的属性(sonName),儿子知道父亲的名字却不知道父亲具体的存款,但是可以通过从父类继承的getMoney()获取存折中的存款信息。
子类可以重写父类的方法,Son类对父类的say方法在保持方法名、参数列表、返回值不变的情况下,对具体的实现进行重写。
父类引用指向子类对象
保持上边代码中Father、Son的内容不变,修改Test类的内容如下:
1 2 3 4 5 6 7 8 public class Test { public static void main (String[] args) { Father s = new Son(); s.say(); s.speak(20 ); } }
首先来分析下代码
Father s = new Son();
: 是向上转型即父类引用指向子类对象,它是对Father的对象的方法的扩充,即Father的对象可访问Son从Father中继承来的和Son复写Father的方法,其它的方法都不能访问,包括Father中的私有成员方法。
s.speak(20);
:此处报错,正是因为speak(int age)
方法属于子类自己的方法而不是从父类继承而来,在向上转型过程中,父类对象s会遗弃子类中的该方法
总结
继承实际上是存在于面向对象程序中的两个类之间的关系。当一个类拥有另一个类的所有数据和操作时,就称这两个类之间具有继承关系!
多态
多态即同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果
多态分为编译时多态和运行时多态
编译时多态也称为静态多态,主要是指方法的重载,它是根据参数列表的不同来区分不同的函数,通过编译之后会变成两个不同的函数,在运行时谈不上多态。
运行时多态称作动态多态,它是通过动态绑定来实现的,也就是我们所说的多态性,只有在运行期才知道是调用的那个类的方法。
多态实现形式
基于继承的多态,基于接口的多态,下面分别给出栗子:
基于继承的多态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class Father { public void say () { System.out.println("我是父亲" ); } } class Son extends Father { @Override public void say () { System.out.println("我是儿子" ); } } class Daughter extends Father { @Override public void say () { System.out.println("我是女儿" ); } } public class Test { public static void main (String[] args) { Father f = new Father(); Son s = new Son(); Daughter d = new Daughter(); f.say(); s.say(); d.say(); } }
执行结果:
通过基于继承来实现多态其实是子类对父类的方法进行了重写,以至于在程序执行时不同的子类对同一个方法会有不同的执行结果
2.基于接口的多态:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public interface Animal { public void say () ; } public class Dog implements Animal { @Override public void say () { System.out.println("狗:汪汪汪" ); } } public class Cat implements Animal { @Override public void say () { System.out.println("猫:喵喵喵" ); } } public class Test { public static void main (String[] args) { Dog dog = new Dog(); Cat cat = new Cat(); dog.say(); cat.say(); } }
执行结果:
通过实现Animal接口,不同的对象会有不同的实现,在程序执行时同样也会有不一样的执行结果。
多态迷魂阵
继承和多态关系密接,多态是基于继承,继承和多态的理解每个人都各有不同,下面可以看下一个非常有趣的题目,被称为多态迷魂阵
出自博客: https://blog.csdn.net/thinkGhoster/article/details/2307001
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 优先级由高到低依次为:this .show(O)、super .show(O)、this .show((super )O)、super .show((super )O)。 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)); } } 执行结果: System.out.println("1--" + a1.show(b)); A and A System.out.println("2--" + a1.show(c)); A and A System.out.println("3--" + a1.show(d)); A and D System.out.println("4--" + a2.show(b)); B and A System.out.println("5--" + a2.show(c)); B and A System.out.println("6--" + a2.show(d)); A and D System.out.println("7--" + b.show(b)); B and B System.out.println("8--" + b.show(c)); B and A System.out.println("9--" + b.show(d)); A and D
参考感谢
面向对象的本质是什么?封装,继承,多态是到底用来做什么的:https://bbs.csdn.net/topics/50019051
多态迷魂阵:https://blog.csdn.net/thinkGhoster/article/details/2307001