1.继承
1.1概念
如果多个类的内容出现重复,把重复的内容放到一个新的类中,通过extends关键字让原来的类和新的类产生关联关系—继承。原来的类是子类,新的类是父类。子类可以继承父类部分信息(父类的私有化信息、构造方法以及构造代码块不能被继承)。
packagecn.tedu.extendsx;
publicclassExtendsDemo1{
publicstaticvoidmain(String[]args){
//创建子类对象---医生类对象
Doctord=newDoctor();
d.treat();
}
}
//定义医疗人员类
//基类、超类、父类
class医疗人员{
//属性
Stringname;
intage;
chargender;
//科室
Stringdept;
//方法
publicvoidtreat(){
System.out.println(name+"在治病救人...");
}
}
//定义代表医生的类
//通过extends关键字让两个类之间产生关联关系----继承
//派生类、子类
classDoctorextends医疗人员{
publicvoidtreat(){
System.out.println(name+"拿着手术刀在治病救人...");
}
}
//代表护士的类
classNurseextends医疗人员{
}
1.2继承方式(单继承)
子类只能有一个父类,一个父类可以有多个子类
Class A extends B{}
class B extends C{}
class C{}(多级继承)
1.3重写(覆盖)
在父子类中出现方法签名一致的方法称之为重写 遵守重写原则(两等两小一大)
方法签名一致(前提)
当父类方法返回值类型是基本类型/void时那么子类方法返回值类型要和父类方法返回值类型保持一致
class 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{
void m(){}
}
class B extends A{
public void m(){}
}
访问权限修饰符—控制在哪个位置关系(定义信息地方和获取信息的地方产生四种位置关系—本类、同包类、其他类、子类)下可以获取定义的信息
1.4super
a.关键字,代表父类对象
b.super语句—在子类构造方法里调用父类构造方法 首行使用
c.每个子类构造方法里默认调用父类无参构造,如果父类没有提供无参构造需要每个子类构造方法里手写super有参调用对应的父类有参构造
d.父类对象优先于子类对象先出现
e.父子类执行顺序(对象级别)—父类构造代码块-父类构造方法-子类构造代码块-子类构造方法
packagecn.tedu.extendsx;
publicclassExtendsDemo3{
publicstaticvoidmain(String[]args){
//创建子类对象
Pigp=newPig(1);
//p.eat();
}
}
//定义代表动物的类
classAnimal{
//父类构造方法
/*publicAnimal(){
System.out.println("父类无参构造");
}*/
publicAnimal(Strings){
}
publicvoideat(){
System.out.println("在吃东西...");
}
publicvoidsleep(){
System.out.println("在睡觉...");
}
}
//定义代表猪的类
classPigextendsAnimal{
//父类对象优先于子类对象先出现
//子类无参光构造
//子类所有的构造方法中都有默认调用父类的无参构造
//如果父类没有提供无参构造,每个子类构造方法都要手写super有参语句调用父类有参构造
publicPig(){
//super语句---调用父类构造方法,要在首行
super("sd");
System.out.println("子类无参构造");
}
publicPig(inti){
super("123");
System.out.println("子类有参构造");
}
//重写eat方法
publicvoideat(){
System.out.println("在无忧无虑的吃东西。。。");
System.out.println("吃着吃着吃饱了。。。想睡觉。。。");
//java中所有的非静态方法与属性都需要通过对象调用
//this?代表当前类的对象
//super代表父类"对象"可以调用父类里的信息
super.sleep();
}
}
2.多态
2.1.概念
代码执行过程中呈现的多种形式
java分为编译时期、运行时期
编译时多态—在编译时期绑定代码 体现形式—重载
public void m(){…}
public void m(int i){…}
运行时多态—在运行时期绑定代码 体现形式—重写、向上造型(继承)
2.2向上造型
可以调用哪些方法看父类,方法的具体执行看子类(父类—目录 子类—正文)
packagecn.tedu.duotai;
publicclassDTDemo{
publicstaticvoidmain(String[]args){
/*//养个宠物
Petp;
//养的宠物就是一条狗
p=newDog();*/
//左边声明类是父类,右边实际创建类是子类---向上造型
Petp=newDog();
//向上造型对象可以调用哪些方法看父类
//方法的具体执行要看子类是否有重写方法
p.eat();
//调用方法
//匿名对象是当做参数来传递
m(newPet());
m(newDog());
m(newCat());
}
//可以接收本类对象以及所有的子类对象
publicstaticvoidm(Petp){//=newPet();=newDog();=newCat();
p.eat();
}
}
//定义代表宠物的类
classPet{
publicvoideat(){
System.out.println("在吃东西。。。");
}
publicvoidsleep(){
System.out.println("在睡觉。。。");
}
}
//定义代表狗的类
classDogextendsPet{
//重写eat方法
publicvoideat(){
System.out.println("在呼哧呼哧的吃。。。");
}
publicvoidbrak(){
System.out.println("在汪汪汪的叫。。。");
}
}
//定义代表猫的类
classCatextendsPet{
//重写eat方法
publicvoideat(){
System.out.println("在呼哧呼哧的吃。。。");
}
publicvoid磨爪子(){
System.out.println("在哼哧哼哧的磨爪子。。。");
}
}
2.3解释重写原则(反证法)
1.子类方法访问权限修饰符要么和父类方法访问权限修饰符范围一致要么大于父类的方法访问权限修饰符的范围
class A{
public void m(){}
}
class B extends A{
void m(){}
}
A a=new B();//向上造型,声明类是A类可以调用A类里m方法,表面这个m方法可以在任意位置被调用。
a.m();//向上造型对象调用方法具体执行看子类是否有重写方法,执行B类里的m方法,表面m方法同包范围内被调用。此时前后有矛盾,代码错误的
2.当父类方法返回值类型是引用类型时,那么子类方法返回值类型要么和父类方法返回值类型一致要么是父类方法返回值类型的子类
class A{
}
class B extends 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类里信息。
A a=c.m();//向上造型执行具体方法看子类D类,调用D类里m方法返回A类对象a,由a对象可以获取A类里信息。此时前后矛盾,证明代码是错误的
2.4多态优点
1.统一参数类型 2.降低耦合度(高内聚、低耦合)
案例:
图形类(两个私有化属性(长和宽)、通过有参构造赋值、提供求周长和面积方法)、矩形类(通过有参构造赋值、提供求周长和面积方法)、正方形类(通过有参构造赋值、提供求周长和面积方法)、圆形类(通过有参构造赋值、提供求周长和面积方法)
package cn.tedu.duotai;
import java.awt.*;
public class TestDemo {
public static void main(String[] args) {
Shape s=new Rectangle(2,3);//向上造型
System.out.println(s.getArea());
System.out.println(s.getGirth());
}
}
//定义一个图形类
class Shape{
//定义父类的私有属性
private double x;
private double y;
//通过有参构造给私有化赋值
public Shape(double x,double y){
this.x=x;
this.y=y;
}
//提供get方法
public double getX() {
return x;
}
public double getY() {
return y;
}
//提供周长和面积的方法
public double getGirth(){
return 0.0;//因为没有确切图形所以不能使用具体公式
}
public double getArea(){
return 0.0;
}
}
//定义代表矩形的类
class Rectangle extends Shape{
//调用父类的有参构造给父类的私有化属性间接赋值
public Rectangle(double x, double y) {
super(x, y);
}
//重写周长和面积的方法
public double getGirth(){
return 2*(getX()+getY());
}
public double getArea(){
return getX()*getY();
}
}
//定义代表正方形的类
class Square extends Rectangle{
//调用父类的有参构造给父类的私有化属性间接赋值
public Square(double x) {
super(x,x);
}
}
//定义代表圆的类
class Circle extends Shape{
//调用父类的有参构造给父类的私有化属性间接赋值
public Circle(double r) {
super(r,r);
}
public double getGirth(){
return 2*3.14*getX();
}
public double getArea(){
return 3.14*getX()*getX();
}
}
3.封装
体现形式—方法,属性私有化并且提供公共的访问方式来进行正常取值和赋值,提高代码数据安全性。
packagecn.tedu.fengzhuang;
publicclassFZDemo{
publicstaticvoidmain(String[]args){
//创建代表人的类的对象
Personp=newPerson();
//给对象属性赋值
//p.name="豆豆";
//调用方法间接给私有化属性进行赋值
p.setAge(-10);
//p.gender='男';
//调用方法间接给私有化属性进行取值
//System.out.println(p.name+","+p.getAge()+","+p.gender);
}
}
//代表人的类
classPerson{
//属性
privateStringname;
//私有化属性,只能在本类中直接使用
privateintage;
privatechargender;
//Alt+Insert---Generate---GetterandSetter
//java自动提供
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
publicintgetAge(){
returnage;
}
publicvoidsetAge(intage){
this.age=age;
}
publicchargetGender(){
returngender;
}
publicvoidsetGender(chargender){
this.gender=gender;
}
/*//定义方法间接的给私有化属性进行赋值
publicvoidsetAge(intage){
if(age<0){
System.out.println("数据有误!!!");
}else{
this.age=age;
}
}
//定义方法间接的给私有化属性进行取值
publicintgetAge(){
returnage;
}*/
/*//有参构造
publicPerson(intage){
if(age<0){
System.out.println("数据有误!!!");
}else{
this.age=age;
}
}*/
}