Java中面向对象的三大特征:继承、封装、多态

面向对象的三大特征

继承、封装、多态

接口(Interface)是用来定义行为的!

抽象类(Abstract Class)是用来实现行为的!

具体类(Class)是用来执行行为的!

使用了对象就叫基于对象,基于对象的基础上增加了继承从而变成了面向对象。

封装

是对象和类概念的主要特征

封装:即把客观事物封装成抽象的类,并且类可以对自己的数据和方法进行权限控制,

封装就是指利用抽象数据类型将数据和基于数据的操作封装在一起,数据被保护在抽象类型的内部,系统的其他部分只有通过包裹在数据外面的被授权的操作,才能够与这个抽象数据类型交流与交互!

封装的优点

  1. 将变化隔离
  2. 便于使用
  3. 提高安全性
  4. 提高重用性

总结

封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据。对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法。

继承

继承:
继承是使用已存在的类的定义作为基础建立新的类,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承我们能够非常方便地复用以前的代码,能够大大的提高开发的效率。

继承的特点:

  1. 子类拥有父类非private的属性和方法。
  2. 子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
  3. 子类可以用自己的方式实现父类的方法。(重写)。
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(){
//子列拥有父类的非private属性
System.out.println("我的父亲是:"+name+"他的存款我不知道...");
//子类拥有父类非private的方法访问权限
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. 运行时多态称作动态多态,它是通过动态绑定来实现的,也就是我们所说的多态性,只有在运行期才知道是调用的那个类的方法。

多态实现形式

基于继承的多态,基于接口的多态,下面分别给出栗子:

  1. 基于继承的多态
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();
}
}

执行结果:

1
2
3
我是父亲
我是儿子
我是女儿

通过基于继承来实现多态其实是子类对父类的方法进行了重写,以至于在程序执行时不同的子类对同一个方法会有不同的执行结果

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

执行结果:

1
2
狗:汪汪汪
猫:喵喵喵

通过实现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

---------- 😏本文结束  感谢您的阅读😏 ----------
评论