0%

java中面向对象

说明

本次笔记主要记录面向对象中的继承、重载重写、多态、抽象、封装、接口、包等概念

java版本为:java version “1.8.0_381”

继承

  • 继承格式有两种,方式一:
1
2
3
4
5
class 父类 {
}

class 子类 extends 父类 {
}
  • 方式二
1
2
3
4
5
6
7
8
9
10
11
public interface A {
public void eat();
public void sleep();
}

public interface B {
public void show();
}

public class C implements A,B {
}
  • 代码实例
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
// 动物类为父类主要包的动作为吃、睡觉、介绍等方法
public class Animal {
private String name;
private int id;
// 重载,主要用来初始化name 和id
public Animal(String myName, int myId) {
name = myName;
id = myId;
}
public void eat(){
System.out.println(name+"正在吃");
}
public void sleep(){
System.out.println(name+"正在睡");
}
public void introduction() {
System.out.println("大家好!我是" + id + "号" + name + ".");
}
}
// 继承父类
public class Mouse extends Animal{
public Mouse(String myName,int myId) {
// 调用的就是Animal父类的重载函数Animal(String myName, int myId)
super(myName, myId);
}
public void eat() {
System.out.println("子类:我吃完了");
}
public void eatTest() {
// 调用父类方法
super.eat();
// this指向子类本身
this.eat();

}
}

//super用来调用父类方法
// this指向子类本身

  • 得到结果
1
2
3
4
5
6
7
8
9
10

public class Main {
public static void main(String args[]) {
Mouse mose = new Mouse("老鼠",1);
mose.eatTest();
}
}
----
老鼠正在吃
子类:我吃完了

重写

  • 重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!
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
// 动物类为父类主要包的动作为吃、睡觉、介绍等方法
public class Animal {
private String name;
private int id;
// 重载,主要用来初始化name 和id
public Animal(String myName, int myId) {
name = myName;
id = myId;
}
public void eat(){
System.out.println(name+"正在吃");
}
public void sleep(){
System.out.println(name+"正在睡");
}
public void introduction() {
System.out.println("大家好!我是" + id + "号" + name + ".");
}
}

//子类
public class Mouse extends Animal{
private String Name;
private int Id;
public Mouse(String myName,int myId) {
// 调用的就是Animal父类的重载函数Animal(String myName, int myId)
super(myName, myId);
this.Name = myName;
this.Id = myId;
}
public void eat() {
System.out.println(this.Name+ ":我吃完了");
}
// 自定义方法
public void dark() {
System.out.println("老鼠可以在叫");
}
}


import java.io.*;

public class Main {
public static void main(String args[]) {
Animal a = new Animal("我是动物父类",1001);
Animal b = new Mouse("老鼠",1);
a.eat(); // 调用父类的eat方法,结果为:我是动物父类正在吃
b.eat(); // 尽管b属于Animal类型,但是它运行的是 Mouse子类的eat,这里重写了父类的eat方法,结果为:老鼠:我吃完
b.sleep(); //同时b调用分类本身的sleep
// 总结:当分类指向子类时
// 1.若子类和父类使用相同方法eat,那么子类中的方法eat重写了父类中的方法eat
// 2.父类可直接调用父类中方法
// 3.子类中的方法在父类中不存在,那么指定调用子类中的方法报错

// 这里标红报错了
b.dark();

}
}

当需要在子类中调用父类的被重写方法时,要使用 super 关键字。继承中已经介绍

重载

  • 重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同
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 class Overloading {
public int test(){
System.out.println("test1");
return 1;
}

public void test(int a){
System.out.println("test2");
}

//以下两个参数类型顺序不同
public String test(int a,String s){
System.out.println("test3");
return "returntest3";
}

public String test(String s,int a){
System.out.println("test4");
return "returntest4";
}

public static void main(String[] args){
Overloading o = new Overloading();
System.out.println(o.test());
o.test(1);
System.out.println(o.test(1,"test3"));
System.out.println(o.test("test4",1));
}
}

实例中重载方法为test

多态

  • 多态存在的三个条件:继承、重写、父类引用指向子类对象,在重写实例中刚好包含了这三要素。

抽象

抽象类

  • 如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。

  • 抽象类除了不能实例化对象之外,类的其它功能依然存在,抽象类必须被继承,才能被使

  • 一个类只能继承一个抽象类,而一个类却可以实现多个接口(留作后续)

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
// 动物类为父类主要包的动作为吃、睡觉、介绍等方法
public abstract class Animal {
private String name;
private int id;
// 重载,主要用来初始化name 和id
public Animal(String myName, int myId) {
name = myName;
id = myId;
}
public void eat(){
System.out.println(name+"正在吃");
}
public void sleep(){
System.out.println(name+"正在睡");
}
public void introduction() {
System.out.println("大家好!我是" + id + "号" + name + ".");
}
}

// 子类
public class Mouse extends Animal{
private String Name;
private int Id;
public Mouse(String myName,int myId) {
// 调用的就是Animal父类的重载函数Animal(String myName, int myId)
super(myName, myId);
this.Name = myName;
this.Id = myId;
}
public void eat() {
System.out.println(this.Name+ ":我吃完了");
}
// 自定义方法
public void dark() {
System.out.println("老鼠可以在叫");
}
}


public class Main {
public static void main(String args[]) {
// 这样不行报错了,不可用直接实例化
// Animal a = new Animal("我是动物父类",1001);
Mouse mouse = new Mouse("老鼠", 1001);
Animal a = new Mouse("老鼠2号", 1002);
a.eat(); //老鼠2号:我吃完了
mouse.eat(); // 老鼠:我吃完了
mouse.sleep();
// 子类中的方法在父类中不存在,调用子类中的方法报错
//a.dark();
}
}

  • 和重写的那个实例非常接近,唯一区别就是不用实例化父类
  • 根据本实例发现既然无法实例化父类,那么父类中的里具体逻辑存在没有必要,只要存在一个方法名就可以了

抽象方法

  • 如果你想设计这样一个类,该类包含一个特别的成员方法,该方法的具体实现由它的子类确定,那么你可以在父类中声明该方法为抽象方法。
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
// 分类
public abstract class Animal {
// 重载,主要用来初始化name 和id
public abstract void eat();
public abstract void sleep(String myName);
public abstract String test();
}

// 子类
public class Mouse extends Animal{
private String Name;
private int Id;
public Mouse(String myName,int myId) {
this.Name = myName;
this.Id = myId;
}
public void eat() {
System.out.println(this.Name+ ":我吃完了");
}
public void sleep(String myName) {
System.out.println(myName+ "在睡觉");
}
public void dark() {
System.out.println("老鼠可以在叫");
}
public String test() {
return "我是一只老鼠";
}
}


public class Main {
public static void main(String args[]) {
Mouse mouse = new Mouse("老鼠", 1001);
Animal a = new Mouse("老鼠2号", 1002);
a.eat(); //老鼠2号:我吃完了
mouse.eat(); // 老鼠:我吃完了
String ts = a.test();
System.out.println(ts); // 我是一只老鼠
a.sleep("我是老鼠啊");// 我是老鼠啊在睡觉
mouse.dark();
// a.dark(); 子类中的方法在父类中不存在,调用子类中的方法报错
}
}
  • 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
  • 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能
  • 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类

接口

  • 接口和抽象类很像,他们是有区别的

  • 接口和抽象类区别

    • 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行

    • 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的

    • 一个类只能继承一个抽象类,而一个类却可以实现多个接口

    • 接口是隐式抽象的,当声明一个接口和方法的时候,不必使用abstract关键字

  • 实战代码

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
// 定义接口
interface Animal {
public void eat();
public void sleep(String myName);
public String test();
}

// 实现接口
public class Mouse implements Animal{
private String Name;
private int Id;
public Mouse(String myName,int myId) {
this.Name = myName;
this.Id = myId;
}
public void eat() {
System.out.println(this.Name+ ":我吃完了");
}
public void sleep(String myName) {
System.out.println(myName+ "在睡觉");
}
public void dark() {
System.out.println("老鼠可以在叫");
}
//如果不实现接口中的test方法,那么就报错了
public String test() {
return "我是一只老鼠";
}
}


public class Main {
public static void main(String args[]) {
Mouse mouse = new Mouse("老鼠", 1001);
mouse.eat(); // 老鼠:我吃完了
String ts = mouse.test();
System.out.println(ts); // 我是一只老鼠
mouse.sleep("我是老鼠啊");// 我是老鼠啊在睡觉
mouse.dark(); // 老鼠可以在叫
}
}

当类实现接口的时候,类要实现(重写)接口中所有的方法,不然报错。否则,类必须声明为抽象的类

接口继承

  • 感觉这里太复杂,不做详细介绍,做个简单笔记。
  • 一个接口能继承另一个接口,和类之间的继承方式比较相似。接口的继承使用extends关键字,子接口继承父接口的方法。

下面的Sports接口被Hockey和Football接口继承:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 文件名: Sports.java
public interface Sports
{
public void setHomeTeam(String name);
public void setVisitingTeam(String name);
}

// 文件名: Football.java
public interface Football extends Sports
{
public void homeTeamScored(int points);
public void visitingTeamScored(int points);
public void endOfQuarter(int quarter);
}

// 文件名: Hockey.java
public interface Hockey extends Sports
{
public void homeGoalScored();
public void visitingGoalScored();
public void endOfPeriod(int period);
public void overtimePeriod(int ot);
}

在Java中,类的多继承是不合法,但接口允许多继承。

在接口的多继承中extends关键字只需要使用一次,在其后跟着继承接口。 如下所示

1
public interface Hockey extends Sports, Event