继承
如果多个类的内容重复出现重复,把重复的内容放到一个新的类中,通过extends关键字让原来的类和新的类产生关联关系—继承。原来的类是子类,新的类是父类。子类可以继承父类部分信息(父类的私有化信息、构造方法以及构造代码块)。
继承方式(单继承)
子类只能有一个父类,一个子类可以有多个子类
Class A extends B{}
Class B extends BC}
Class C{}-------(多级继承)
public class ExtendsDenmo1 {
public static void main(String[] args) {
//创建子类对象---医生类对象
Doctor d = new Doctor();
d.treat();
}
}
//定义医疗人员类
//通过extends关键字让两个类之间产生关联关系----继承
class Doctor extends 医疗人员{//派生类、子类
@Override
public void treat() {
System.out.println(name+"拿着手术刀在救人");
}
}
class Nurse extends 医疗人员{
}
//代表医生的类
class 医疗人员{//基类、超类、父类
//属性
String name;
int age;
char gender;
//科室
String dept;
//方法
public void treat(){
System.out.println(name+"在治病救人...");
}
}
//代表护士的类
/*class Nurse{
//属性
String name;
int age;
char gen;
//科室
String dept;
//方法
public void treat() {
System.out.println(name+"在治病救人...");
}
}*/
重写(覆盖)
在父子类中出现签名一致的方法称之为重写方法,遵守重写原则(两等两小一大)
方法签名一致
当父类方法返回值类型是基本类型/void时那么子类方法返回值类型要和父类方法返回值类型保持一致
calss A{
public int m(){return 1;}
}
class B extends A{
public int m(){return 2;}
}
当父类方法返回值类型是引用类型时,那么子类方法返回值类型要么和父类方法返回值类型一致,要么是父类方法返回值类型的子类
Class A{}
Class B extends A{}
Class C{
public A m(){return null;}
}
Class D extends C{
public A/B m(){return null;}
}
子类方法访问权限修饰符和么和父类方法的访问权限修饰符范围一致,要么比父类方法访问权限修饰符的范围要大
Class A{
public m(){}
}
Class B extend A{
public void m(){}
}
访问权限修饰符—控制在哪个位置关系(定义信息地方和获取信息的地方产生四种位置关系—本类、同胞类)下可以获取定义的信息
public class A {
protected void m(){}
}
public class B extends A{
public static void main(String[] args) {
//创建A类对象
//A a =new A();
//m方法定义在A类中,获取信息的地方是B类中,残生位置关系---其他类
//被protected修饰的信息在其他类位置关系下获取不到信息
//a.m();
//创建子类对象
//被protected修饰的信息吐过在其他位置是父子类也能获取信息
//被protected修饰的信息在其他类位置,保证子类对象本类中使用才能调用这个信息
B b =new B();
b.m();
}
}
class C extends A{
public void n(){
//创建子类对象
C c = new C();
//
c.m();
//创建子类对象
B b = new B();
//创建子类对象没有在本类中使用调不到
//b.m();
}
}
super
a.关键字,代表父类对象
b.super语句—在子类构造方法里调用父类构造方法
c.每个子类构造方法里默认调用父类无参构造,如果父类没有提供无参构造需要每个子类构造方法里手写super有参调用对应的父类有参构造
d.父类对象优先于子类对象先出现
e.父子类执行顺序(对象级别)------父类构造代码块-父类构造方法-子类构造代码块-子类构造方法
public class ExtendsDemo3 {
public static void main(String[] args) {
//创建子类对象
Pig p = new Pig();
p.eat();
}
}
//定义代表动物的类
class Animal{
//父类构造方法
/*public Animal(){
System.out.println("父类无参构造方法");
}*/
public Animal(String s){
}
public void eat(){
System.out.println("在吃东西...");
}
public void sleep(){
System.out.println("在睡觉...");
}
}
//定义代表猪的类
class Pig extends Animal{
//父类对象和子类对象?
//子类无参构造
//子类所有的构造方法中都默认调用父类的无参构造
//如果父类没有提供无参构造,每个字类构造方法都要手写super有参语句调用父类有参构造
public Pig(){
//super语句---调用父类构造方法,要在首行
super("12");
System.out.println("子类无参构造");
}
//子类有参构造
public Pig(int i){
//
super("33");
System.out.println("子类有参构造");
}
//重写get方法
@Override
public void eat() {
System.out.println("在无忧无虑的吃东西...");
System.out.println("吃着吃着吃饱了...想睡觉...");
//java中所有的非静态方法与属性都需要通过对象调用
//this?代表当前类的对象
//super代表父类"对象"可以调用父类里的信息
super.sleep();
}
}
多态
代码执行过程中呈现的多种形式
java分为编译时期、运行时期
编译时多态—在编译时期绑定代码 体现形式—重载
public void m(){...}
public void m(int i){...}
运行时多态—在运行时期绑定代码 体现形式—重写、向上造型
向上造型
可以调用哪些方法看父类,方法的具体执行看子类(父类—目录、子类—正文)
解释重写原则(反证法)
1.子类方法访问权限修饰符要么和父类方法访问权限修饰符范围一致,要么大于父类的方法访问权限修饰符的范围
Class A{
public void m(){}
}
Class B extend A{
void m(){}
}
A a = new B();
//向上造型,声明类是A类可以调用A类里m方法,表面这个m方法可以再任意位置被调用。
a.m();
//向上造型对象调用方法具体执行看子类是否有重写方法,执行B类里的m方法,表面m方法同包范围内被调用。此时前后有矛盾,代码错误
2.当父类方法返回值类型是引用类型时,那么子类方法返回值类型要么和父类方法返回值类型一致,要么是父类方法返回值类型的子类
Class A{
}
Class B extend A{
}
Class C{
public B m(){return null;}
}
class D extends C{
public A m(){return null;}
}
C c = new D();//向上造型对象c,调用声明类C类m方法返回B类对象可以获取B类里信息。
c.m();//向上造型执行具体方法看子类D类,调用D类里m方法返回A类对象a,由a对象可以获取A类里信息。
//此时前后矛盾,证明代码是错误的
多态优点
1.统一参数类型
2.降低耦合度(高内聚、低耦合)
案例:
图形类(两个私有化属性(长和宽)、通过有参构造赋值、提供求周长和面积方法)、矩形类(通过有参构造赋值、提供求周长和面积方法)、正方形类(通过有参构造赋值、提供求周长和面积方法)、圆形类(通过有参构造赋值、提供求周长和面积方法)
public class TXDemo {
public static void main(String[] args) {
//向上造型
TuXing s1 = new JuXing(2,3);
System.out.println(s1.getArea());
System.out.println(s1.getGirth());
}
}
//图形类
class TuXing{
//定义私有属性
private double a;
private double b;
//有参构造---通过有参构造给私有化属性进行赋值
public TuXing(double a,double b){
this.a = a;
this.b = b;
}
//提供get方法间接获取私有化属性值
public double getA() {
return a;
}
public double getB() {
return b;
}
//提供周长面积计算方法
public double getGirth(){
return 0.0;//因为没有确切图形不能使用具体计算公式
}
public double getArea(){
return 0.0;//因为没有确切图形不能使用具体计算公式
}
}
//矩形类
class JuXing extends TuXing{
//有参构造---调用父类有参构造给父类私有化属性间接赋值
public JuXing(double a,double b){
super(a,b);
}
//重写周长面积计算方法
public double getGirth(){
return 2*(getA()+getB());//求周长
}
public double getArea(){
return getA()*getB();//求面积
}
}
//正方形类
class ZhengFang extends JuXing{
//有参构造--调用父类有参构造给父类私有化属性间接赋值
public ZhengFang(double a){
super(a,a);
}
}
//圆形类
class Yuan extends TuXing{
//有参构造--调用父类有参构造给父类私有化属性间接赋值
public Yuan(double r) {
super(r, r);
}
//重写周长面积计算方法
public double getGirth(){
return 3.14*2*getA();//求周长
}
public double getArea(){
return getA()*getA()*3.14;//求面积
}
}