------- android培训、java培训、期待与您交流! ----------
Day08继承 final 抽象类
多个类中存在相同属性和行为时,将这些相同的内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继那个类即可。多个类可以称为子类,单独这个类称为父类或者超类。子类可以直接访问父类中的非私有的属性和行为。
A:Java只支持单继承,不支持多继承(子类调用父类方法的不确定性)。但是它支持多层继承(接口与接口之间可以存在多继承)
B:父类有的,子类也有,而且子类可以改变(更改父类的属性值,重写父类的成员方法),父类没有的子类也可以进行增加。
C:父类的属性和方法可以被继承,但是构造方法不能被继承,子类的构造方法隐式的调用父类的无参构造方法,当父类没有无参构造方法时,子类需要使用super来显示的调用父类的构造方法。
-------学生类继承了人类,拥有了人类的成员变量(name和age)和成员方法(eat和sleep方法)
class Person{
String name;
int age;
Person(){}
public void sleep(){
System.out.println("睡觉");
}
public void eat(){
System.out.println("吃饭");
}
}
class Student extends Person{//学生继承人类
String sid;//学号
public void study(){
System.out.println("我宁愿做一头快乐的猪");
}
}
A:成员变量
**子类直接继承了本身没有的成员变量。
**当子类中有和父类同名的成员变量时。在方法中打印的是子类自己的。
**当子类方法中有局部变量和成员变量同名,在方法中打印的是局部变量。
也就是说:先在局部范围找,其次在本类中找,最后在父类中找。如果找到,立马输出。
如果找不到,就报错。
B:成员方法
**父类中的方法和子类中没有同名的情况。子类就把父类的方法直接继承过来使用。
**子类中存在了和父类同名的方法时,子类就会去调用子类中的方法。而且这种现象
在java中称为重写(override),复写,覆盖。
重载(overload)与重写(override)的区别:
重载(overload):
**在同一个类中。
**方法名相同,参数列表不同。
重写(override)
**存在于子父类当中。
**方法的声明一致。(名称和参数)
**子类的访问权限不能低于父类的访问权限。
简单说:用子类对象调用方法时,首先子子类中找,其次在父类中找。如果找到,会直接操作。如果找不到,就报错。
父类静态方法只能被子类静态方法重写。(一般不会出现这种情况,静态属于类不再属于对象)
注意:
**父类中的私有方法不可以被覆盖。
**在子类覆盖方法中,要想继续使用被覆盖的父类方法可以通过super.方法名获取。
格式:super.方法名();
This代表本类对象的引用。
Super代表父类所属的空间,并不是一个对象。
C:构造方法
**子类中所有的构造函数默认都会访问父类中空参数的构造函数
**因为每一个构造函数的第一行都有一条默认的语句super();
this() 代表本类的无参构造
super() 代表父类的无参构造
**当父类中没有空参数的构造函数时,子类的构造函数必须通过this或者super语句指定要访问的构造函数。
为什么子类的构造函数都要去默认访问父类的构造函数?
因为子类继承了父类,可以访问父类中的已有的一些属性,在子类进行实例化的时候必须要为父类中的属性进行分配空间,并要进行初始化,所以必须要访问一次父类的构造函数,看看父类是如何对其属性进行初始化的,所以子类要实例化对象时,必须要先看父类的初始化过程。
结论:父类的构造函数,既可以给本类对象初始化,也可以给子类对象初始化。
A:当某个事物是另一个事物的一种的时候,就用继承。
B:如何判断一个事物是另一个事物的一种?
对于A类和B类。
我们可以假设它们存在着继承关系。比如:A extends B
如果A是B的一种,那么继承成立。他们就具有继承关系。否则,继承关系不成立。
最终的意思。
可以用于修饰类,修饰成员变量,成员方法。
A:final修饰的类不能被继承。
B:fainl修饰的成员方法不能被重写。
C:final修饰的成员变量是一个常量。
final double PI = 3.14;
A:多了一个关键字修饰。
B:变量名大写。
C:值不能被改变。
注意:用final修饰的变量必须先赋初始值再操作,否则编译失败。
**抽象就是从多个事物中将共性的,本质的内容抽取出来。
**Java中可以定义没有方法体的方法,该方法的具体实现由子类完成,该方法称为抽象方法,包含抽象方法的类就是抽象类。
**多个对象都具备相同的功能,但是功能具体内容有所不同,那么在抽取过程中,只抽取了功能定义,并未抽取功能主体,
那么只有功能声明,没有功能主体的方法称为抽象方法。
**抽象类和抽象方法都必须用abstract关键字修饰。
**抽象方法一定要在抽象类中。
**一个类继承了抽象类:
要么该类实现抽象类中的所有抽象方法。
要么该类实现部分抽象方法或者根本不实现任何抽象方法,这个时候需要把自身定义为抽象类。
**抽象类不能够被实例化。也就是说不可以通过new关键字创建对象。
为什么抽象类不能被实例化?
因为抽象类中有抽象方法,你创建对象后,别人调用抽象方法是没有任何意义的。
**有人说:因为抽象类没有构造方法是错误的。
那么抽象类的构造有意义吗?有。
抽象类本身是一个类,所有它有构造方法。它不能实例化不代表它的构造方法没有意义。它可以用于为子类对象进行实例化。
雇员示例
需求:公司中程序员有姓名,工号,薪水,工作内容。
项目经理除了有姓名,工号,薪水,还有奖金,工作内容。对给出需求进行数据建模。
数据建模:就是把我们给出的事物描述出来。说白了就是把类给设计出来。
我想让项目经理继承程序员。
这是时候,我们说项目经理的是程序员的一种,发现可以。
但是呢,分析又有小问题了:项目经理的工作内容和程序员不一样。
不管怎么说:程序员和经理都是公司的员工。
所以,我们分析出一个员工类,来描述共性的内容。
然后把程序员和经理具体的描述下。
代码:
abstract class Employee{
String name;//姓名
String id;//工号
double salary;//薪水
Employee(){}
Employee(String name,String id,double salary){
this.name = name;
this.id = id;
this.salary = salary;
}
abstract void work();//工作内容
abstract void showInfo();//个人信息
}
class Worker extends Employee{
Worker(){}
Worker(String name,String id,double salary){
super(name,id,salary);
}
void work(){
System.out.println("好好学习,天天向上");
}
void showInfo(){
System.out.println(name+" "+id+" "+salary);
}
}
class Manager extends Employee{
double bonus;//奖金
Manager(){}
Manager(String name,String id,double salary,double bonus){
super(name,id,salary);
this.bonus = bonus;
}
void work(){
System.out.println("想怎么着能让你更大的能量(更累,累并快乐着)");
}
void showInfo(){
System.out.println(name+" "+id+" "+salary+" "+bonus);
}
}
class AbstractDemo5 {
public static void main(String[] args) {
Worker w = new Worker("慈禧","cixi888",10000);
w.work();
w.showInfo();
Manager m = new Manager("李莲英","lilianyin250",2000,16000);
m.work();
m.showInfo();
}
}
A:抽象类中是否有构造方法?
**因为抽象类它本身也是一个类,所以它有构造方法。
**虽然它不能够被实例化,但是它的构造方法也是有用的。用于给子类做初始化。
B:抽象类中可不可以没有抽象方法?
**可以的。
**有什么用?让类不能够被实例化。在awt里面有体现。
C:抽象关键字abstract不可以和哪些关键字共存?
**final 它修饰的方法不能被重写。而这样就和抽象产生了冲突。
***final abstract void show(); 这是不行的。
**private 它修饰内容只能在本类中被访问。
***private abstract void show(); 这是不行的。
**static 它修饰的内容可以直接被类访问,而访问抽象的内容没有意义。
***static abstract void show(); 这是不行的。
------- android培训、java培训、期待与您交流! ----------