《day09---继承-抽象类-接口》

Posted 太自由

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《day09---继承-抽象类-接口》相关的知识,希望对你有一定的参考价值。

//面向对象_继承_概述---单继承_多继承。
//描述学生。
/*
class Student
{
    //属性。
    String name;
    int age;

    //行为:
    void study()
    {
        System.out.println("good good study");
    }
}

class Worker
{
    //属性:
    String name;
    int age;

    //行为;
    void work()
    {
        System.out.println("hard work");
    }
}
*/

/*
为了提高代码的复用性,只建立一份代码就可以了。
一个类只要和另一个类产生关系就可以了。
关系:继承。
发现了获取到所需内容的同时也获取到不该具备的内容。
为什么?
发现原来这两个类之间根本就不存在继承关系。

怎么解决呢?
找到学生和工人的共性类型。将需要提供复用的代码进行抽取。
定义到一个共性的类中。
Person name age.

怎么在代码体现中,让学生和Persong产生关系呢?
只要通过关键字extends(继承),就可以了。
*/
class Person
{
    //属性:
    String name;
    int age;
}

class Student extends Person//学生继承了Person,学生就是子类,Person就是父类(基类。超类)
{
    //行为:
    void study()
    {
        System.out.println("good good study");
    }
}

class Worker extends Person
{
    //行为;
    void work()
    {
        System.out.println("hard work");
    }
}

/*
面向对象的另一个特征:继承。
好处:提高了代码的复用性。让类和类产生了关系,给另一个特征。多态提供了前提。

什么时候定义继承?
必须保证类与类之间有所需(is a)关系.xxx是zzz中的一种。
学生是人中的一种。
苹果是水果中的一种。
狗是犬科中的一种。

在Java中继承的体现。
Java允许单继承。不直接支持多继承。将多继承进行其他方式的体现。
单继承:一个子类只能有一个父类。
多继承:一个子类可以有多个父类。

看上去,多继承很厉害!为什么?
class Fu1
{
    void show1()
    {}
}

class Fu2
{
    void show2()
    {}
}
//多继承。
class Zi extends Fu1,Fu2
{

}

Zi z = new Zi();
z.show1();
z.show2();
//问题随之而来,
万一多个父类具备了相同的功能呢?
class Fu1
{
    void show()
    {
        sop("fu1 show run");
    }
}

class Fu2
{
    void show()
    {
        sop("fu2 show run");
    }
}
//多继承。
class Zi extends Fu1,Fu2
{

}
Zi z = new Zi();
z.show();//调用就会产生不确定性。所以java保留了多继承的好处。
         //改良了它的弊端,用多实现来体现。用多实现来体现。
         //即将学到。
----------------------------------
java中还支持多重继承。
class A
{}
class B extends A
{}
class C extends B
{}

//形成继承体系。

学习继承体系时,应该参阅顶层的类中的内容。
了解这个体系的基本功能。

使用这个体系功能,需要创建最子类的对象。
看顶层,建底层。


*/
class ExtendsDemo
{
    public static void main(String[] args) 
    {
        Student stu = new Student();
        stu.name = "xiaoming";
        stu.age = 12;
        stu.study();
    }
}
 1 //面向对象_继承_子父类中成员变量的特点。
 2 /*
 3 继承出现后,在代码中的体现。
 4 
 5 重点在于成员的体现:
 6 1,成员变量。重点明确原理。
 7     特殊情况:
 8         子父类中定义了一模一样的成员变量。
 9         都存在于子类对象中。
10         如何在子类中直接访问同名的父类中的变量呢?
11         通过关键字super来调用。
12 
13         super和this的用法很相似。
14         this代表的是本类对象的引用。
15         super代表的是父类的内存空间。
16 
17         注意:这种情况开发见不到。因为父类一旦描述完了属性,
18               子类直接使用就可以了。
19 
20 2,成员函数。
21 3,构造函数。
22 */
23 
24 //父类
25 class Fu
26 {
27     /*private int num1 = 3;*///父类中私有的内容子类不可以直接访问。
28     int num = 3;
29 }
30 
31 class Zi extends Fu
32 {
33     /*int num2 = 4;*/
34     int num = 4;
35     void show()
36     {
37     //    System.out.println("num1="+num1);
38     //    System.out.println("num2="+num2);
39         System.out.println("fu num="+super.num);
40         System.out.println("zi num="+this.num);
41         System.out.println(this);
42     }
43 }
44 class  ExtendsDemo
45 {
46     public static void main(String[] args) 
47     {
48         Zi z = new Zi();
49     //    System.out.println(z.num1);
50     //    System.out.println(z.num2);
51         z.show();
52     }
53 }
 1 /*
 2 子父类中成员函数的特点。
 3 特殊情况:
 4 子父类中定义了一模一样的函数。
 5 运行的结果是子类的函数在运行。
 6 这种情况在子父类中,是函数另一个的特性,Override 重写(覆盖,复写)
 7 
 8 重写什么时候用?
 9 举例:
10 //描述手机
11 class Phone
12 {
13     //打电话。
14     void call()
15     {}
16 
17     //来点显示。
18     void show()
19     {
20         System.out.println("电话号码");
21     }
22 }
23 
24 Phone p = new Phone();
25 p.show();
26 
27 //随着电话的升级,只显示号码不爽,希望显示姓名,大头贴等。
28 修改源码,虽然费劲,但是可以解决问题,但是不利于后期的维护和扩展。
29 为了扩展方便,新功能是不是新的电话具备呢?
30 单独描述,单独封装。新电话也是电话中的一种,继承。直接获取父类中的功能。
31 但是新电话的来电显功能已经变化了。需要重新定义。
32 那么定义一个新功能合适吗?比如NewShow,不合适,因为父类已经将来点显功能定义了。
33 子类完全不需要重新定义新功能,直接用就可以了,如果子类的来显功能内容不同。
34 只需要保留来显功能,定义子类的内容即可,这就是重写的应用。
35 class NewPhone extends Phone
36 {
37     void show()
38     {
39         //System.out.println("电话号码");
40         super.show();//如果还需要父类中原有的部分功能,可以通过super调用。
41         sop("姓名");
42         sop("大头贴");
43     }
44 }
45 
46 
47 重写的注意事项:
48 1,子类覆盖父类,必须保证权限要大于或者等于父类的权限。(private除外,因为子类
49    中不能直接访问父类中的private。)
50 Fu:
51 void show(){}
52 
53 Zi:
54 void show(){}
55 
56 2,静态覆盖静态。
57 
58 
59 写法上注意:不行一模一样:函数的返回值类型 函数名 函数的参数列表都要一样。
60 */
61 class Fu
62 {
63     void show()
64     {
65         System.out.println("fu show1 run");
66     }
67 }
68 class Zi extends Fu
69 {
70     static void show()
71     {
72         System.out.println("zi show2 run");
73     }
74 }
75 class  ExtendsDemo2
76 {
77     public static void main(String[] args) 
78     {
79         Zi z = new Zi();
80         z.show();
81 
82     }
83 }
  1 /*
  2 子父类中构造函数的特点。
  3 当子父类中都有构造函数时,发现结果为:
  4 Fu constructor run
  5 zi constructor run
  6 先执行了父类的构造函数,再执行子类中的构造函数。
  7 为啥呢?
  8 因为子类中的所有的构造函数中的第一行都有一句隐式额语句Super();
  9         //默认调用的是父类中空参数的构造函数。
 10 子类中构造函数为什么有一句隐式的super呢?
 11 原因:子类会继承父类中的内容,所以子类在初始化时,必须先到父类中去
 12       执行父类的初始化动作。
 13       才可以更方便子类使用。
 14 
 15 当父类中没有空参数构造时,子类的构造函数必须显示的super语句指定
 16 要访问的父类中构造函数。
 17 
 18 这就是传说中的子类实例化过程。
 19 
 20 细节:
 21 1,如果子类的构造函数第一行写了this调用了本类的构造函数,那么super调用父类的
 22   语句还有吗?
 23   没有的,因为this()或者super(),只能定义在构造函数的第一行,因为初始化动作要先执行。
 24 
 25 2,子类构造函数里有super,那么父类构造函数有没有super呢?
 26   是有的,记住:只要是构造函数默认第一行都是super();
 27   父类的父类是谁呢?super 调用的到底是谁的构造函数呢?
 28   Java体系在设计时,定义了一个所有对象的父类Object.
 29 
 30 
 31 总结:
 32 类中的构造函数默认第一行都由隐式的super语句,在访问父类中的构造函数。
 33 所以父类的构造函数既可以给自己的对象初始化,也可以给自己的子类对象初始化。
 34 
 35 如果默认的隐式super语句没有对应的构造函数,必须在构造函数中通过this或者super
 36 的形式明确要调用的构造函数。
 37 
 38 问题:
 39 1,this 语句和super语句是否可以在同一个构造函数中出现呢?不行:因为必须定义在第一行。
 40 2,为什么要定义在第一行呢?因为初始化动作要先执行。
 41 */
 42 
 43 class Fu extends Object
 44 {
 45     int count = 3;
 46     //Fu(){}
 47     Fu()
 48     {
 49         //super();
 50         //显示初始化。
 51         System.out.println("Fu constructor run..A.."+count);
 52     }
 53     Fu(int x)
 54     {
 55         //显示初始化。
 56         System.out.println("Fu constructor run..."+x);
 57     }
 58 }
 59 
 60 class Zi extends Fu
 61 {
 62     Zi()
 63     {
 64         System.out.println("zi constructor run..C..");
 65     }
 66     Zi(int x)
 67     {
 68         this();
 69         System.out.println("zi constructor run..."+x);
 70     }
 71 }
 72 class ExtendsDemo 
 73 {
 74     public static void main(String[] args) 
 75     {
 76         //New Zi();
 77         new Zi(6);
 78         new Student("lisi",21);
 79     }
 80 }
 81 
 82 /*
 83 
 84 class Fu
 85 {
 86     Fu()
 87     {
 88         System.out.println("Fu constructor run..A..");
 89     }
 90     Fu(int x)
 91     {
 92         //显示初始化。
 93         System.out.println("Fu constructor run..B..");
 94     }
 95 }
 96 
 97 class Zi extends Fu
 98 {
 99     Zi()
100     {
101         //super();
102         System.out.println("Fu constructor run..C..");
103     }
104     Zi(int x)
105     {
106         //super();
107         System.out.println("Fu constructor run..D..");
108     }
109 }
110 class ExtendsDemo 
111 {
112     public static void main(String[] args) 
113     {
114         new Zi();
115         new Zi(6);//打印结果是A C A D.
116     }
117 }
118 
119 */
120 
121 //子类的实例化过程的应用。也是super调用的应用。
122 //什么时候用super调用父类中的构造函数,只要使用父类的指定初始化动作,
123 //就在子类中使用super()调用就可以了。
124 class Person
125 {
126     private String name;
127     private int age;
128     public Person(String name,int age)
129     {
130         this.name = name;
131         this.age = age;
132     }
133     public void setName(String name)
134     {
135         this.name = name;
136     }
137     public String getName()
138     {
139         return name;
140     }
141     public void setAge(int age)
142     {
143         this.age = age;
144     }
145     public int getAge()
146     {
147         return age;
148     }
149 }
150 class Student extends Person
151 {
152     public Student(String name,int age)
153     {
154         //调用父类,使用父类的初始化动作。
155         super(name,age);
156     }
157     
158 }
159 
160 class Worker extends Person
161 {
162     public Worker(String name,int age)
163     {
164         //调用父类,使用父类的初始化动作。
165         super(name,age);
166     }
167 }
 1 //final关键字。
 2 /*
 3 继承的弊端:打破封装性。
 4 不让其他类去继承该类,就不会有重写。
 5 怎么能实现呢?通过java中的关键字来实现。final(最终化)
 6 
 7 【final】
 8 是一个修饰符。可以修饰类,方法,变量(成员变量,局部变量,静态变量)
 9 【特点】
10 1,final修饰的类是一个最终类,不能再派生子类。
11 如果类中出现部分可以重写,部分不可以?怎么办?只要让指定的方法最终化就可以了。
12 2,final修饰的方法是最终方法,不可以重写。
13 3,fianl修饰变量是一个常量。只能被赋值一次。
14 【什么时候需要在程序中定义final常量呢?】
15 当程序中一个数据使用时是固定不变的,这时为了增加阅读性,可以给该数据起个名字。
16 这就是变量,为了保证这个变量的值不被修改,加上final修饰,这就是一个阅读性很强的
17 常量。书写规范,被final修饰的常量名所有的字母都是大写的。如果由多个单词组成,单词
18 之间用下划线连接。
19 */
20 /*final*/ class Fu
21 {
22     /*final*/ void show()
23     {
24         //调用到一些系统的功能。
25         //功能的内容是不可以改变的。
26     }
27 }
28 
29 class Zi extends Fu
30 {
31     static final int number = 9;//这个编译会失败,final修饰的变量必须赋初值。
32     static final double PI = 3.14;//为了访问方便,直接用static修饰,可以直接用类名调用。
33     //覆盖
34     void show()
35     {
36         final int count = 21;
37         //count = 2;//失败。
38         System.out.println(count);
39     }
40 }
41 
42 class  FinalDemo
43 {
44     public static void main(String[] args) 
45     {
46         System.out.println("Hello World!");
47     }
48 }
 1 /*
 2 描述狗,行为,吼叫。
 3 描述狼,行为:吼叫。
 4 发现他们之间有共性,可以进行向上抽取。
 5 当然是抽取它们的所属共性类型,犬科。
 6 犬科这类事物,都具备吼叫行为。但是具体怎么叫,是不确定的,是由具体的子类来
 7 明确的。
 8 这些不具体的功能,需要在类中标识出来,通过java中的关键字来体现。
 9 
10 定义了抽象函数的类也必须别abstract修饰。
11 
12 抽象类,在描述事物时,没有足够的信息描述一个事物,这时该事物就是抽象事物。
13 */
14 
15 /*
16 【抽象类的特点】
17 1,抽象类和抽象方法都需要被abstract修饰。
18 抽象方法一定要定义在抽象类中。
19 2,抽象类不可以创建实例。原因就在于调用抽象方法没意义。
20 3,只有覆盖了抽象类中所有的抽象方法后,其子类才可以实例化。
21    否则,该子类还是一个抽象类。
22 
23    之所以继承,更多的是在思想上,是面对共性类型操作会更简单。
24 
25    【细节问题】
26    1,抽象类一定是一个父类。
27       是的,因为是不断向上抽取而来的。
28 
29    2,抽象类中是否有构造函数。
30       有,虽然不能给自己的对象初始化,但是可以给自己的子类对象初始化。
31       抽象类和一般类的异同点:
32       相同:
33             1,它们都是用来描述事物的。
34             2,它们之中都可以定义属性和行为。
35       不同:
36                1,一般类可以具体的描述事物,
37               抽象类描述事物的信息不具体。
38             2,抽象类中可以多定义一个成员,抽象汉。
39             3,一般类可以创建对象,而抽象类不能创建对象。
40 
41    3,抽象类中是否可以不定义抽象方法。
42       是可以的。那这个抽象类的存在到底有什么意义呢?仅仅是不让不让该类创建对象。
43 
44    4,抽象类关键字不可以哪些关键字共存。
45       1,final. 被final修饰的类是最终类,不能被继承,而抽象类就是要被子类继承的。
46       2,private. 被private修饰的方法,其子类无法直接访问,而抽象的方法就是要让子类覆盖的。
47       3,static.  被static修饰的方法要随着类的加载而加载,且可以直接由类名调用。
48 
49 */
50 
51 abstract class 犬科 //extends Object
52 {
53     abstract void 吼叫();//抽象函数,需要abstract修饰。并分号;结束
54 }
55 
56 //代码体现。
57 class Dog extends 犬科
58 {
59     void 吼叫()
60     {
61         System.out.println("汪汪汪汪");
62     }
63 }
64 
65 
66 class Wolf extends 犬科
67 {
68     void 吼叫()
69     {
70         System.out.println("嗷嗷嗷嗷");
71     }
72 }
73 
74 class  AbstractDemo
75 {
76     public static void main(String[] args) 
77     {
78         System.out.println("Hello World!");
79     }
80 }
 1 /*抽象类联系
 2 需求:公司中程序员有姓名,工号,薪水,工作内容。
 3 项目经理除了姓名,工号,薪水,还有奖金,工作内容。
 4 对给定的需求进行数据建模。
 5 
 6 在问题领域中先找寻其中的涉及的对象。
 7 程序员:
 8     属性:姓名,工号,薪水。
 9     行为:工作。
10 
11 项目经理:
12     属性:姓名,共号,薪水。
13     行为:工作。
14 
15 这些对象是否有关系呢?因为发现了它们之间的共性,应该存在着关系。
16 可以将他们的共性向上抽取到共性类型,员工。
17 员工:
18     属性:姓名,工号,薪水。
19     行为:工作。
20 发现员工的工作内容本身就不具体,应该是抽象的,由具体的子类来体现。
21 
22 */
23 
24 abstract class Employee
25 {
26     private String name;
27     private String id;
28     private double pay;
29 
30     /**
31     构造一个员工对象,一初始化就具备三个属性。
32     */
33 
34     Employee(String name,String id,double pay)
35     {
36         this.name = name;
37         this.id = id;
38         this.pay = pay;
39     }
40 
41     /**
42     工作行为:
43     */
44     public abstract void work();
45 }
46 
47 //具体的子类实现,程序员:
48 class Programer extends Employee
49 {
50     Programer(String name,String id,double pay)
51     {
52         super(name,id,pay);
53     }
54     public void work()
55     {
56         System.out.println("code....");
57     }
58 }
59 
60 //具体的子类,经理:
61 class Manager extends Employee
62 {
63     //特有属性。
64     private double bouns;
65     public Manager(String name,String id,double pay,double bouns)
66     {
67         super(name,id,pay);
68         this.bouns = bouns;
69     }
70 
71     public void work()
72     {
73         System.out.pritnln("work");
74     }
75 }
76 class AbstractTest
77 {
78     public static void main(String[] args) 
79     {
80         System.out.println("Hello World!");
81     }
82 }
/*
抽象类中是可以定义抽象方法的,当一个抽象类中方法全是抽象的,
这时,可以通过另一种特殊的形式来体现。

不再用class来定义,用接口来表示。

接口该如何定义呢?
interface

abstract class Demo
{
    abstract void show1();
    abstract void show2();
}

*/

/*
接口中的成员已经被限定为固定的几种。
【接口的定义格式先介绍两种】
1,定义变量,但是变量必须有固定的修饰符修饰,public static final所以接口中的变量
   也称之为常量。
2,定义方法,方法也有固定的修饰符,public abstract
接口中的成员都是公共的。

【接口的特点】
1,接口不能创建对象。
2,子类必须覆盖掉接口中所有的抽象方法后子类才可以实例化。
   否则子类是一个抽象类。
*/
interface Demo//定义一个名称为Demo的接口。
{
    public static final int NUM = 3;
    public abstract void show1();
    public abstract void show2();
}


//定义子类去覆盖接口中的方法。子类必须和接口产生关系,类与类的关系是继承
//类与接口之间是实现。
class Demoimpl implements Demo //子类实现接口。
{
    //重写接口中的方法。
    以上是关于《day09---继承-抽象类-接口》的主要内容,如果未能解决你的问题,请参考以下文章

Python开发基础-Day18继承派生组合接口和抽象类

day24 继承 接口 多态

Java基础面试每日3题:day04

抽象类与接口 day-11.2

day21

day21接口类和抽象类,隔离原则,开放封闭原则,多态