1.多态:事物在不同环境下表现出来的不同形态
(1)三个前提:
a.要有继承或者实现关系
b.要有方法的重写
c.要有父类的引用指向子类的对象
(2)两种调用
同名的成员变量:父类的
同名的成员方法:子类的
(3).二种转型
向上转型:Person p = new Teacher();
向下转型:Teacher t = (Teacher)p;
注意:
(1):对象在调用同名变量时,父类必须有该变量,没有则报错;运行时也是运行父类中的变量;
(2).对象在调用重写方法时,父类必须有该变量,没有则报错;但是运行时却是运行子类中的方法;
(3).普通的继承和多态之间的区别
继承:子类有,就用子类;子类没有则用父类;父类也没有就报错
多态:引用永远指向的是子类内存区中父类的那一片小内存,永远优先寻找父类中的成员
运行同名变量时,编译看父类 运行看父类
运行重写方法时,编译也是看父类,运行时因为重写的机制导致运行子类中的重写方法
public class ObjectDemo2 {
public static void main(String[] args) {
Person per =new Student();
System.out.println(per.name);
per.sleep();
}
}
abstract class Person{
String name ="黄儿去找女朋友";
public abstract void sleep();
}
class Student extends Person{
@Override
public void sleep() {
System.out.println("学生睡觉晚");
}
}
abstract class Teacher extends Person{
@Override
public void sleep() {
}
public void show(){
}
}
2.抽象类:就是用abstract 修饰的类:
(1).抽象方法格式:
abstract 修饰符 返回值类型 方法名(参数列表);
(2).抽象类的定义格式:
abstract class 类名{}
注意:
(1). 抽象类中可以没有抽象方法,有抽向方法的类一定是抽象类;当我们把一个方法定义成抽象方法以后,我们必须要将类定义成抽象类
(2). 抽象类不能创建对象,需要使用子类向上转型
(3). 抽象的子类要么实现抽象类中所有的抽象方法,要么自己是一个抽象类
(4). 抽象类有构造方法
(5). abstract 不能和final共存
(6).抽象类不能创建对象但是还需要抽象类的对象?
可以使用抽象类多态的形式定义对象,然后调用变量或者方法
/*
定义一个抽象类形状,包含两个方法,求周长和面积
定义一个类长方形,实现抽象类中的方法
定义一个类圆,实现抽象类中的方法
在测试类中测试
*/
public class ObjectDemo3 {
public static void main(String[] args) {
Rectangle rect= new Rectangle();
rect.width=2;
rect.height=4;
rect.Perimeter();
rect.Area();
Circle cc = new Circle();
cc.r=3;
cc.Area();
cc.Perimeter();
}
}
abstract class Shape{
public abstract void Perimeter();
public abstract void Area();
}
class Rectangle extends Shape{
double width;
double height;
@Override
public void Perimeter() {
System.out.println("周长为:"+2*(width+height));
}
@Override
public void Area() {
System.out.println("面积为:"+width*height);
}
}
class Circle extends Shape{
double r;
@Override
public void Perimeter() {
System.out.println("周长为:"+2*r*Math.PI);
}
@Override
public void Area() {
System.out.println("面积为:"+r*r*Math.PI);
}
}
3.接口(功能的扩展,原先不具备的功能,经过后天的学习学会的)
(1).定义格式: (interface 近似于 class)
interface 接口名{}
注意:
(1). 接口中只能定义常量,默认public static final修饰
(2). 接口中只能定义抽象方法(1.8之前) 默认是public abstract 修饰
(3). 接口不能创建对象,使用子类向上转型
(4). 接口的子类: 实现了接口的类 class 子类名 implements 接口1,接口2{}
(5). 接口的子类要么实现接口中所有的抽象方法要么自己是一个抽象类
(6). 一个类可以实现多个接口,并且可以在继承类的同时实现多个接口
(7). 接口中没有构造方法
(8). jdk8之后接口中可以定义已经实现的方法,但是必须使用static/default 修饰
(9). 接口不能实现接口,只能继承接口,并且可以多继承
class 子类名 implements 接口1,接口2{}
4.抽象类和接口的区别:
(1).一个类最多只能继承一个抽象类,但是可以实现多个接口
(2).抽象类中既可以定义变量也可以定义常量,接口中只能定义常量
(3).抽象类中既可以定义抽象方法,也可以定义非抽象方法,接口中能定义抽象方法(jdk8之前)
(4).接口中没有构造方法,抽象类中有构造方法
(5).接口只能继承接口不能实现接口,并且可以多继承
/*
编写一个抽象类Animal,抽象类中包括属性:name(String类型),抽象方法:speak()。
编写一个宠物接口pet,接口中包括方法:eat()。
再编写一个类cat,实现该接口和抽象类中的所有方法。
speat(): “miao, my name is xxx”
eat(): “I want to eat some fish”
在main中进行测试,输出:
给猫赋值一个名字,调用speak,eat 方法
*/
public class ObjectDemo7 {
public static void main(String[] args) {
Cat cat = new Cat();
cat.name = "毛毛";
cat.eat();
cat.speak();
}
}
abstract class Animal {
String name;
public abstract void speak();
}
interface Pet {
public void eat();
}
class Cat extends Animal implements Pet {
@Override
public void eat() {
System.out.println("我想吃鱼");
}
@Override
public void speak() {
System.out.println("喵喵喵,我叫" + name);
}
}