在继承的情况下,子类的方法满足以下条件:
1、方法名相同
2、参数列表相同
3、返回值类型相同,或者是父类返回值类型的子类
4、访问修饰符的权限不能小于父类方法
5、抛出的异常不能大于父类(严于)
多态
抽象类abstract关键字修饰类
抽象类不能被实例化(不能创建对象)含有抽象方法的类必须被声明为抽象类,抽象类必须被继承,抽象方法必须被重写
抽象方法:
抽象方法必须在抽象类中
抽象方法没有结构体
子类继承抽象类的时候,必须实现父类的抽象方法,除非这个子类也是抽象类
TestFinal.java
public class TestFinal{
public static void main(String[] args){
T t=new T;
//t.i=8;
}
}
class T{
final int i=8;
public void m(final Cat cat){//不能让这个引用指向其他的猫
j=9;//报错不能指定最终参数j(final int j 的时候)
}
}
public final void m(){
//
}
Final关键字:
public final class String /public final class Math /public final class Boolean
不能被继承,重写方法
final的变量值不能被改变(成员变量、局部变量)
final的方法不能被重写
final的类不能被继承
java中是单继承、但是生活中存在多继承的现象,不可以这么写就是使用接口
接口:本质上讲,接口是一种特殊的抽象类,在这个抽象类里面,所有的方法都是抽象方法,
所有的成员变量都必须是public static final的,只包含常量和方法的定义,而没有变量和方法的实现。
public interface Runner{
public static final int id=1;
public void start();//所有的方法不用写abstract实际都是abstract的
}
一个类可以实现多个接口
接口中声明的属性默认是public static final也只能是public static final的
一个接口里面的方法只能是public的抽象方法
接口和实现类之间存在多态性 只能看到实现类中自己的方法
Singer s=new Student(); //把student当作singer来看,每一个接口暴露了对象的一部分方法,使用什么样的接口,只能访问这个接口对应的方法
s.sing();
只要实现了这个接口的任意一个类的对象都可以往里面传,new这个对象出来就可以往里面传,
重写了我sing的方法,我实际调用的就是重写的方法,接口本质上仍然是一个类,帮助我们实现多重继承
f(Singer s){
s.sing();
}
第三章总结:
内存分析贯穿始终
对象和类的概念
类是具有同样特征的同一类事物的抽象
对象是这类事物的特殊的实例
类和对象直接的关系:关联、继承、聚合(聚集、组合)、多态、实现
面向对象设计思想:和面向过程不一样,这个问题里有哪些类哪些对象,类里面有哪些属性哪些方法,类和类之间有什么关系,有没有继承、多态的关系
Class、new关键字,引用的概念:一小块内存指向一大块内存,new一般和构造方法一起使用,构造一个新对象的时候调用的方法,和类同名,没有返回值,void都不可以写。
方法的重载,方法名字一样,参数列表不同(参数的类型不一样或者参数的个数不一样)
this关键字:当前对象,你现在在调用哪个方法,this指的就是谁,内存里new出一个对象来,有一个自己的引用指向自身
static的成员变量是属于所有类的,一般分配在data区域里面,属于这个类的所有对象,属于整个类,不需要new这个对象就可以去访问它。非static的必须去new一个对象出来才可以去访问它的值,static不需要,只要用类名.就可以访问它的值,或者来访问这个方法。
package解决类重名的问题,约定俗成、公司域名倒过来
访问控制:private 修饰成员变量,只有自己能访问,出了类没有人能访问它
default同一个包里面其他类可以访问
protected它的子类可以访问
public所有类都能访问
default和public还可以修饰class
所有的关键字都可以修饰内部类,
extends继承,一个类从另外一个类继承,封装了这样一种语义,XXX是一种XXX,只要说通了,它们之间是一种继承关系。继承下来相当于拥有了那个类所有的成员变量,所有的方法,包括private的,但是对于private的成员变量,拥有了所有权但是没有使用权
overwrite:方法的重写
父类实现一方法不满意,重写。重写的时候有一个best practise最佳的实践
final的变量不能改变值,final的方法不能被重写,final的class不能被继承
Object
toString封装了一个对象在一个字符串上的表现,可以重写它,写一个字符串,来表现它
upcasting父类引用指向子类对象/接口的引用指向实现的对象,向上转型
downcasting向下转型
多态:要有继承、要有重写、父类引用指向子类对象
多态也叫动态绑定dynamic binding 迟绑定 late binding:new的是哪个类,我就找那个类对象的方法,这叫动态绑定
abstract class有抽象方法的类叫做抽象类,抽象方法只有定义,没有实现
interface接口
特殊的抽象类,所有的方法都是抽象方法,而且都是public的,所有的成员变量都是public static final的
接口和接口之间可以互相继承,类和类之间可以互相继承,类和接口之间只能实现implements
一个类可以实现多个接口,多个类可以实现一个接口,内存里可以看见这个对象的一部分方法,这就是接口。
Cat:
package cn.kgc.kb09;
/**
* @Author: ChaoKeAiMuZhi
* @Date: 2020/7/22 16:13
* @Description:
**/
public class Cat extends Pet {
@Override
public void toHospital() {
if(getHealth()<50){
setHealth(90);
System.out.println("猫有九条命,不用治");
}
}
public void playwithBall(){
System.out.println("猫玩毛线球");
}
@Override
public void eat() {
setHealth(getHealth()+3);
System.out.println("猫吃鱼,健康值加3");
}
}
Dog
package cn.kgc.kb09;
/**
* @Author: ChaoKeAiMuZhi
* @Date: 2020/7/22 15:59
* @Description:
**/
public class Dog extends Pet {
String strain;
public String getStrain() {
return strain;
}
public void setStrain(String strain) {
this.strain = strain;
}
@Override
public void toHospital() {
if(getHealth()<50){
setHealth(60);
System.out.println("给狗狗治疗,吃药,打针");
}
}
@Override
public void eat() {
setHealth(getHealth()+5);
System.out.println("狗狗吃骨头,健康值加5");
}
public void catchFrisbee(){
System.out.println("狗狗接飞盘");
}
}
Fish:
package cn.kgc.kb09;
/**
* @Author: ChaoKeAiMuZhi
* @Date: 2020/7/22 16:37
* @Description:
**/
public class Fish extends Pet {
@Override
public void toHospital() {
}
@Override
public void eat() {
System.out.println("鱼吃虾米,健康值加3");
}
}
Master:
package cn.kgc.kb09;
/**
* @Author: ChaoKeAiMuZhi
* @Date: 2020/7/22 16:06
* @Description:
**/
public class Master {
//全局静态常量,只有一个副本,不会创建
public static final String CAT="cat";
public static final String DOG="dog";
public static final String PENGUIN="penguin";
public void cure(Pet p){
p.toHospital();
}
public void feed(Pet p){
p.eat();
}
//在返回值的部分使用多态
//代理模式
public Pet getPet(String type){
Pet p=null;
if(CAT.equals(type)){
//猫类型
p=new Cat();
}
if(DOG.equals(type)){
p=new Dog();
}
if(PENGUIN.equals(type)){
p= new Penguin();
}
return p;
}
}
Penguin
package cn.kgc.kb09;
/**
* @Author: ChaoKeAiMuZhi
* @Date: 2020/7/22 15:59
* @Description:
**/
public class Penguin extends Pet {
public void toHospital(){
if(getHealth()<50){
setHealth(70);
System.out.println("给企鹅治疗,吃鱼、疗养");
}
}
@Override
public void eat() {
System.out.println("企鹅吃鱼,健康值加3");
}
public void swim(){
System.out.println("企鹅在南极游泳");
}
}
Pet
package cn.kgc.kb09;
/**
* @Author: ChaoKeAiMuZhi
* @Date: 2020/7/22 15:06
* @Description:
**/
public abstract class Pet {
private String name;
private int health;
private int love;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getHealth() {
return health;
}
public void setHealth(int health) {
this.health = health;
}
public int getLove() {
return love;
}
public void setLove(int love) {
this.love = love;
}
//重写equals方法
@Override
public boolean equals(Object obj) {
if(this==obj){
return true;
}
if(obj instanceof Pet){
Pet p=(Pet) obj;
//自定义比较规则
//如果宠物的名称相同,则认为是同一个对象
if(this.name!=null && this.name.equals(p.name) && this.love!=0 &&this.love==p.love && this.health!=0 &&this.health==p.health){
return true;
}
}
return false;
}
/*@Override
public String toString(){
return "我叫"+this.name+",我的健康值为:"+this.health+",与主人的亲密度为:"+this.love;
}*/
/*@Override
public String toString() {
return "Pet{" +
"name='" + name + '\'' +
", health=" + health +
", love=" + love +
'}';
}*/
public abstract void toHospital();/*{
System.out.println("宠物去医院");
}*/
public abstract void eat();
}
TestMaster:
package cn.kgc.kb09;
/**
* @Author: ChaoKeAiMuZhi
* @Date: 2020/7/22 16:22
* @Description:
**/
public class TestMaster {
public static void main(String[] args) {
Master m=new Master();
//Pet p=m.getPet("Dog");
Pet p=new Cat();
Dog d=new Dog();
System.out.println(p);
//涉及类型转换的时候,如果有多种可能,那么最好用instanceof关键字进行类型判断
if(p instanceof Cat){
Cat c=(Cat) p;
c.playwithBall();
}
if(p instanceof Dog){
Dog c=(Dog) p;
System.out.println("转成狗类");
}
m.feed(d);
m.cure(d);
/*//出现异常java.lang.ClassCastException
Dog d=(Dog)p;*/
}
}
TestPet
package cn.kgc.kb09;
/**
* @Author: ChaoKeAiMuZhi
* @Date: 2020/7/22 15:20
* @Description:
**/
public class TestPet {
public static void main(String[] args) {
/*Pet p1=new Pet();
Pet p2=new Pet();
p1.setName("宠物1号");
p2.setName("宠物1号");
p1.setHealth(96);
p2.setHealth(96);
p1.setLove(92);
p2.setLove(92);
System.out.println(p1.toString());
//System.out.println();默认会去调用object的toString方法,我们重写了
System.out.println(p2);
//System.out.println(p1==p2);
System.out.println(p1.equals(p2));*/
//父类引用指向子类对象
Pet d=new Dog();//子类对象引用父类类型,多态的基础
//这时候不能直接使用子类的属性和方法
System.out.println(d);
Master master=new Master();
/*master.cure(d);
Penguin p=new Penguin();
master.cure(p);
Cat c=new Cat();
master.cure(c);
master.feed(c);
master.feed(d);
master.feed(p);*/
Pet pet=master.getPet("penguin");
System.out.println(pet);
if(pet instanceof Dog){
Dog dog=(Dog)pet;
dog.catchFrisbee();
}
if(pet instanceof Penguin){
Penguin penguin=(Penguin)pet;
penguin.swim();
}
}
}