Java从入门到精通五(Java面向对象下,封装,继承,多态)
Java从入门到精通(Java面向对象下,封装,继承,多态)
一:封装(Encapsulation)
1:封装的概念
在程序设计中,封装是一种将数据实现包装,隐藏起来的方法。数据是非常重要的,封装的出现,提高了数据的安全性。不能通过直接去访问数据,只能用程序中提供的可访问数据的接口。另外一点,就是通过封装,让我们更加方便的去访问自己所存储的数据,还有就是便于维护。
2:封装实现的过程
<1>修改类属性
常见的修改就是修改类中定义变量的访问权限。我们用private关键字修饰。被private修饰的属性只能被本类访问,其它的类是无法直接访问的,注意并不是不能访问。
对类属性的权限private化
package java_practice;
public class Student {
private String name;
private int age;
}
- 1
- 2
- 3
- 4
- 5
name,age都用private关键字修饰,使得name,age只能被本类访问。其它的外部类是不能访问的。这样相当于对外部类隐藏了属性,使得对属性的访问具有了一定的限制。
<2>提供接口
这里的接口是提供给外部类访问程序的接口。是两个方法。get(),set(),get()用于获取到值,set()用于对属性赋值。
具体如下示例
package java_practice;
public class Student {
private String name;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
这样就基本实现了一个简单的封装。
3:外部类通过提供方法访问权限属性
上代码举例
package java_practice;
public class Student_Test {
public static void main(String args[])
{
Student s = new Student();//创建Student类的对象
s.setAge(18);
s.setName("li");
System.out.println(s.getName()+"今年"+s.getAge()+"岁");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
输出结果:
可以看到这样就可以正常访问了。
4既然接口都给了,封装还有什么意义?还不是可以访问?
可能你有这样的疑惑,特别是对于刚学的小白来说,不明白这样的意义。但是事实上并不是这样的,我们粉装的意义就是权限,是访问的限制规定,而不是禁止。当然你可以禁止,但是如果是禁止的话,也就没必要提供接口方法了。
怎么体现?我们还拿上段代码举例。我们可以在Student类中的set方法设置一些限定,以限制测试主类的属性的不恰当的修改。
来看代码
package java_practice;
public class Student {
private String name;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
if(age<0||age>200)
{
System.out.println("赋值不合理");
}
System.exit(0);//甚至你可以直接退出
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
然后测试类这样做了
package java_practice;
public class Student_Test {
public static void main(String args[])
{
Student s = new Student();//创建Student类的对象
s.setAge(201);
s.setName("li");
System.out.println(s.getName()+"今年"+s.getAge()+"岁");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
输出
你看,这样就对访问修改做了限制。当然你也可以这样。对get()方法里面进行操作。让用户传入参数,判断参数是否与你设定的一样,如果不一样,那就拒绝让外部类获取到值。这样就类似了一种口令。
二:继承(inheritance)
1:继承的概念
在程序设计中,面向对象也包含了继承这么一种设计理念。java中实现了类的继承,被继承的类叫做父类,继承的类叫子类。子类可以拥有父类的某些属性,注意是某些,不是全部。
继承的方式有多种,单继承,多继承,多重继承。java是不支持多继承的。也就是说,你一个子类不能继承多个父类,但是多个子类可以继承同一个父类。
2: 单继承
单继承很好理解,就是只有一个子类直接继承,子类没有被其它类继承。
//父类
package java_practice;
public class Student {
private String name;
private int age;
public String place;
static int number = 666;
public int getAge() {
return age;
}
public void describe()
{
System.out.println("学生:"+name_1);
}
public void setAge(int age) {
if(age<0||age>200)
{
System.out.println("赋值不合理");
}
System.exit(0);//甚至你可以直接退出
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//子类
package java_practice;
public class Studen_1 extends Student{
public static void main(String args[])
{
System.out.println(number);//父类的number没有被private修饰
//System.out.println(name);name没有被拥有,所以无法输出
Student s = new Student();
System.out.println(s.getName());//如果要访问,只能用提供的接口方法
}
}
- 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
子类可以直接访问父类的共有变量这些属性,那么方法是怎么访问呢?对于一般的方法的访问方法
我们在分类写一个一般的共有方法,子类可以拥有这个属性。
子类调用父类的一般方法(当然该方法也被子类所拥有)
package java_practice;
public class Studen_1 extends Student{
public static void main(String args[])
{
System.out.println(number);//父类的number没有被private修饰
//System.out.println(name);
Student s = new Student();
System.out.println(s.getName());
Studen_1 s1 = new Studen_1();
s1.describe();//子类通过对象调用方法
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
子类的继承父类的时候必须用做的那些事情。
必须调用父类的构造函数,如果父类有默认的构造函数,子类实例化会自动调用,如果父类没有声明默认的构造函数的话(无形参构造函数),子类构造函数必须通过super调用父类的构造函数。另外需要注意的是,子类构造函数必须通过super调用父类的构造函数。
在new()对象的时候,父类中的构造函数就会自动执行。
我在父类中写了一个无参构造方法
//父类
package java_practice;
public class Student {
private String name;
private int age;
public String place;
static int number = 666;
String name_1 = "jgdabc";
public Student(){
System.out.println("Hello");
}
public void describe()
{
System.out.println("学生:"+name_1);
}
public int getAge() {
return age;
}
public void setAge(int age) {
if(age<0||age>200)
{
System.out.println("赋值不合理");
}
System.exit(0);//甚至你可以直接退出
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//子类
package java_practice;
public class Studen_1 extends Student{
public static void main(String args[])
{
System.out.println(number);//父类的number没有被private修饰
//System.out.println(name);
Student s = new Student();
System.out.println(s.getName());
Studen_1 s1 = new Studen_1();
s1.describe();
}
}
- 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
我们看执行结果
可以看到父类这个无参构造方法执行了两次。所以说,每一次new对象的时候这个无参构造方法会自动执行。
那么对于父类的有参构造方法呢?我们还是来看代码。我们在父类中写一个有参构造函数,将父类的无参覆盖掉。如果父类只有有参构造方法,那么子类必要用super关键字进行实现。我们需要这样做。看示例代码
//父类
package java_practice;
public class Student {
private String name;
private int age;
public String place;
static int number = 666;
String name_1 = "jgdabc";
/*public Student(){
System.out.println("Hello");
}*/
public void describe()
{
System.out.println("学生:"+name_1);
}
public int getAge() {
return age;
}
public void setAge(int age) {
if(age<0||age>200)
{
System.out.println("赋值不合理");
}
System.exit(0);//甚至你可以直接退出
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//子类
package java_practice;
public class Studen_1 extends Student{
public Studen_1(int age) {
super(age);
//TODO Auto-generated constructor stub
}
public static void main(String args[])
{
System.out.println(number);//父类的number没有被private修饰
//System.out.println(name);
Studen_1 s = new Studen_1(18);
s.describe();
}
}
- 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
说明一下,父类的构造器是不能被子类继承的。子类默认继承父类的属性和方法,但不会继承父类的构造器,而是在子类被实例化时会默认调用父类的空构造器。子类在创建的时候会调用自己的空构造器,并在空构造器会隐式调用super(),即父类的空构造器。如果父类的构造器被重载,那么子类中的构造器也必须初始化父类的构造器,否则会报编译错误。
3: 多重继承
多重继承指的是什么
假如一个Student类作为父类,那么一个Student1类可以继承Student,Student2继承Student1。以此类推,但是你不能Student2既继承Student又继承Student1。
那么多重继承有什么特点呢?
我们还是代码举例说明
package java_practice;
public class Student {
private String name;
private int age;
public String place;
static int number = 666;
String name_1 = "jgdabc";
public Student(int age)
{ this.age = age;
System.out.println("我今年"+age+"岁");
}
// public Student(){
// System.out.println("Hello");
// }
public void describe()
{
System.out.println("学生:"+name_1);
}
public int getAge() {
return age;
}
public void setAge(int age) {
if(age<0||age>200)
{
System.out.println("赋值不合理");
}
System.exit(0);//甚至你可以直接退出
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package java_practice;
public class Studen_1 extends Student{
public Studen_1(int age) {
super(age);
//TODO Auto-generated constructor stub
}
public static void main(String args[])
{
System.out.println(number);//父类的number没有被private修饰
//System.out.println(name);
Studen_1 s = new Studen_1(18);
}
}
package java_practice;
public class Student2 extends Studen_1 {
public Student2(int age) {
super(age);
//TODO Auto-generated constructor stub
}
public static void main(String args[]){
Student2 s2 = new Student2(19);
s2.describe();
}
}
- 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
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
可以看到多重继承的类依然可以访问其父类的父类的方法,也同样需要调用好有参构造器(直接父类的有参构造器)(父类的无参被有参覆盖掉。需要我们手动调用)同样也具有同样的非公有属性。
4:多个子类继承继承同一个父类
package java_practice;
public class Student2 extends Studen_1 {
public Student2(int age) {
super(age);
//TODO Auto-generated constructor stub
}
public static void main(String args[]){
Student2 s2 = new Student2(19);
s2.describe();
}
}
package java_practice;
public class Student3 extends Student {
public Student3(int age) {
super(age);
//TODO Auto-generated constructor stub
}
public static void main()
{
}
}
- 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
三:多态(polymorphism)
1:多态的概念
多态是java面向对象的另外一个特征
简明的说,就是一个行为的不同表现形式。如何理解。比如说吃饭的的行为,你吃饭和别人吃饭的动作肯定是和别人多多少少都有不同表现的,那么这个就是多态。
2:实现多态的过程
1:实现继承(上述已经说明,不再赘述)
2:实现方法重写(一般方法)
注意:方法重写和方法重载是不一样的
首先说方法重载,简单就是一个类中多个同名方法,但是参数列表不一样(参数个数或者参数的类型)
而重写发生在继承关系,子类对父类的一般方法进行重写,参数列表以及方法名必须一致,然后内部的行为不一样。
举例一个方法重写的例子
同样给出父类和子类,我们对父类的describe()方法进行重写
//父类
package java_practice;
public class Student {
private String name;
private int age;
public String place;
static int number = 666;
String name_1 = "jgdabc";
public Student(int age)
{ this.age = age;
System.out.println("我今年"+age+"岁");
}
// public Student(){
// System.out.println("Hello");
// }
public void describe()
{
System.out.println("学生:"+name_1);
}
public int getAge() {
return age;
}
public void setAge(int age) {
if(age<0||age>200)
{
System.out.println("赋值不合理");
}
System.exit(0);//甚至你可以直接退出
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//子类
package java_practice;
public class Studen_1 extends Student{
public Studen_1(int age) {
super(age);
//TODO Auto-generated constructor stub
}
public void describe()
{
System.out.println("Long long ago!");
}
public static void main(String args[])
{
System.out.println(number);//父类的number没有被private修饰
//System.out.println(name);
Studen_1 s = new Studen_1(18);
s.describe();
}
}
- 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
- 71
- 72
实现多个子类重写父类相同的方法,便很生动的体现了多态。
可见子类重写父类的一般方法后,当子类再次调用这个方法就会调用到重写后的这个方法
3:对父类的引用指向子类对象(我们又可称为向上转型)
下面举一个例子。
package java_practice;
public class Student {
private String name;
private int age;
public String place;
static int number = 666;
String name_1 = "jgdabc";
public Student(int age)
{ this.age = age;
System.out.println("我今年"+age+"岁");
}
public Student() {
}
// public Student(){
// System.out.println("Hello");
// }
public void describe()
{
System.out.println("学生:"+name_1);
}
public int getAge() {
return age;
}
public void setAge(int age) {
if(age<0||age>200)
{
System.out.println("赋值不合理");
}
System.exit(0);//甚至你可以直接退出
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package java_practice;
public class Studen_1 extends Student{
public Studen_1(int age) {
super(age);
//TODO Auto-generated constructor stub
}
public Studen_1() {
}
public void describe()
{
System.out.println("Long long ago!");
}
}
package java_practice;
public class Student2 extends Studen_1 {
public Student2(int age) {
super(age);
//TODO Auto-generated constructor stub
}
public Student2() {
}
public void describe()
{
System.out.println("no body but you!");
}
}
package java_practice;
public class Student3 extends Student {
public Student3(int age) {
super(age);
//TODO Auto-generated constructor stub
}
public Student3() {
}
public void describe()
{
System.out.println("Believe you self!");
}
}
package java_practice;
public class test {
public static void main(String args[])
{
Student s = new Studen_1();//向上转型
s.describe();
Studen_1 s1 = new Studen_1();//进行向下转型
s1.describe();
show(new Student2());
show(new Student3());
}
public static void show(Student a)
{
if(a instanceof Studen_1)
{
Studen_1 s1 = (Studen_1) a;
s1.describe();
}else if (a instanceof Student2)
{
Student2 s2 = (Student2)a;
s2.describe();
}else if (a instanceof Student3)
{
Student3 s3 = (Student3)a;
s3.describe();
}
}
}
- 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
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
首先定义一个Student主类,Student_1继承Student,Student_2继承Student_1,Student_3继承Student2,然后我们再定义一个测试类,在测试类中进行具体对象的实现,并展示多态的效果。
。
我们也可以完全将父类写成一个抽象类,然后对抽象类中的属性或者方法进行具体的实现。
欢迎留言指点。
文章来源: daodaozi.blog.csdn.net,作者:兰舟千帆,版权归原作者所有,如需转载,请联系作者。
原文链接:daodaozi.blog.csdn.net/article/details/122724047
- 点赞
- 收藏
- 关注作者
评论(0)