学习资料来自:黑马程序员,内容仅为学习记录,侵删
多态
多态:事务存在的多种形态
多态的前提:1、有继承关系;2、重写父类方法;3、父类引用指向子类对象
面向对象
面向对象多态中成员访问特点
1.成员方法(动态绑定):编译看左边(父类),运行看右边(子类)
2.成员变量:编译看左边(父类),运行看左边(父类)
3. 静态方法:编译看左边(父类),运行看左边(父类)
练习代码
public class Demo07_Polymorphic {
public static void main(String[]agrs){//多态:事务的多种形态 多态的前提:1、有继承关系;2、重写父类方法;3、父类指向子类
xiaomi mi = new xiaomi();
mi.call();
mi.method();
//面向对象多态中成员访问特点——成员方法(动态绑定):编译看左边(父类),运行看右边(子类)
phone p = new xiaomi(); //父类指向子类;输入“小米手机打电话”,在编译时看父类有没有方法,运行时看的是子类方法
p.call();
//在这里,p是父类phone类型的变量但实际上指向的是子类xiaomi,method()是一个静态方法,编译器会根据p的声明类型phone来调用phone类中的方法
p.method(); //面向对象多态中成员访问特点——静态方法:编译看左边(父类),运行看左边(父类)
//面向对象多态中成员访问特点——成员变量:编译看左边(父类),运行看左边(父类)
System.out.println(p.num);//输出10
System.out.println(mi.num);//输出20
}
}
class phone{
int num = 10;
public void call(){
System.out.println("手机打电话");
}
public static void method(){
System.out.println("我是父类中的方法");
}
}
class xiaomi extends phone{ //子类xiaomi继承父类phone
int num = 20; //在访问这个成员变量前会有一个super指向父类成员变量
public void call(){ //重写父类方法call
System.out.println("小米手机打电话");
}
public static void method(){
System.out.println("我是子类中的方法");
}
}
运行结果
多态中向上转型和向下转型
**向上转型:**父类引用指向子类对象称为向上转型。向上转型后的父类引用只能调用父类的属性,若子类重写了父类的方法,则通过父类引用调用的是子类重写后的方法(即 override),该调用过程即为“动态绑定”。
**向下转型:**已经向上转型的子类对象指向父类引用称为向下转型,但并不是所有的对象都可以向下转型,只有当这个对象原本就是子类对象通过向上转型得到的时候才能够成功转型,在向下转型前,通过instanceof 判断某对象是否是某类的实例。
多态的好处:1、提高代码的维护性(继承保证)2、提高了代码的扩展性(有多态保证)3、可以当作形式参数接收任意子类对象
多态的弊端是不能使用子类的特有属性和行为
public class Demo07_SuperMan {
public static void main(String[]agrs){
/*
* 多态的好处:1、提高代码的维护性(继承保证)2、提高了代码的扩展性(有多态保证
* */
person p = new Superman();//父类指向子类,向上转型
System.out.println(p.name);//面向对象多态中成员访问特点——成员变量:编译看左边(父类),运行看左边(父类)
p.谈生意();//面向对象多态中成员访问特点——成员变量:编译看左边(父类),运行看右边(子类)
//p.fly();多态中父类无法使用子类特有属性和行为,无法在父类person中找到方法无法编译
Superman s = (Superman) p;//向下转型
s.fly();
}
}
class person{
String name = "John";
public void 谈生意(){
System.out.println("谈生意");
}
}
class Superman extends person{
String name = "Superman";
public void 谈生意(){
System.out.println("谈一个大生意");
}
public void fly(){
System.out.println("飞出去救人");
}
}
编译结果
练习代码
public class Demo07_Animals {
public static void main(String[] agrs) {
method(new sheep());
method(new bossy());
}
/*
* 多态的好处:1、提高了代码的维护性;2、提高了代码的扩展性;3、可以当作形式参数接收任意子类对象
*/
public static void method(animals a) { //当作形式参数接收任意子类对象
if (a instanceof sheep) { // instanceof判断前后的数据类型是的一致
sheep s = (sheep) a;//向下转型
s.eat();
s.action();
} else if (a instanceof bossy) {
bossy b = (bossy) a;
b.eat();
b.action();
} else {
a.eat();
}
}
}
class animals {
public void eat() {
System.out.println("动物吃东西");
}
}
class sheep extends animals {
public void eat() {
System.out.println("绵羊吃草");
}
public void action() {
System.out.println("绵羊咩咩叫");
}
}
class bossy extends animals {
public void eat() {
System.out.println("牛吃树叶");
}
public void action() {
System.out.println("牛哞哞叫");
}
}
运行结果
抽象类
抽象类概述:抽象类就是看不懂的
抽象类特点:
- 抽象类和抽象方法必须用abstract关键字修饰,如abstract class 类名、public abstract void 方法名()
- 抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或接口
- 抽象类实例化:按照多态的方式由具体的子类实例化,抽象类多态
- 抽象类的子类:1、要么是抽象类;2、要么重写抽象类中的所有抽象方法
抽象类的成员特点
- 既可以是变量,也可以是常量,abstract不能修饰变量
- 有构造方法,用于子类访问父类数据的初始化
- 成员方法既可以是抽象的,也可以是非抽象的
练习代码
public class Demo07_Abstract {
/*
*抽象概述:抽象就是看不懂的
*抽象类和抽象方法必须用abstract关键字修饰,如abstract class 类名、public abstract void 方法名()
*抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或接口
*抽象类实例化:按照多态的方式由具体的子类实例化,抽象类多态
*抽象类的子类:1、要么是抽象类;2、要么重写抽象类中的所有抽象方法 */
//一个类如果没有抽象方法,可以定义抽象类,这样可以不让其他类创建本类对象,交给子类完成
public static void main(String[] agrs) {
//Car c = new Brand();因为子类是抽象类不能实例化,如果想要注释代码编译可以去掉子类的抽象类abstract修饰
//c.color();
}
}
abstract class Car { //抽象类
public abstract void color(); //抽象方法
/* public static abstract void print();
public final abstract void print();
private abstract void print();*/
}
abstract class Brand extends Car{
public void color(){
System.out.println("子类的这辆车是红色的");
}
}
抽象类中的成员方法特性:
- 抽象方法强制要求子类做的事(统一规则);
- 非抽象方法,子类继承提高代码的复用性
练习代码2
public class Demo07_AbstractTest {
}
/*
* 抽象类中的成员方法特性:
* 1、抽象方法强制要求子类做的事(统一规则);
* 2、非抽象方法,子类继承提高代码的复用性*/
abstract class AbstractTestFather {
//抽象类的成员变量可以是变量也可以是常量,不可以修饰成员变量(因为抽象代表看不懂的,无法作为修饰)
int num = 10;
final int num1 = 20;
public AbstractTestFather() {}//构造方法:用于子类访问父类数据的初始化
public abstract void play();//成员方法:可以是抽象的
}
abstract class AbstractTestSon extends AbstractTestFather {
public void play() {//成员方法:可以是非抽象的,子类需要重写父类中抽象类的方法
System.out.println("play game");
}
}
一个抽象类没有抽象方法,可以定义抽象类,这样做的目的是不让其他类创建本类对象,交给子类完成
abstract不能和哪些关键字共存
- abstract 和private
被abstract修饰的是为了让子类看到并强制重写
被private修饰是不让子类访问 - abstract 和final
被abstract修饰的是为了让子类看到并强制重写
被final修饰的不让重写 - abstract 和static
被abstract修饰的方法没有方法体
被static修饰的可以用类名.调用,但是被abstract修饰的方法没有方法体
接口
接口概述:
从狭义角度讲接口就是Java中的interface
从广义角度讲对外提供规则的就是接口
接口特点:
- 接口用关键字interface表示,接口不能实例化,按照多态中父类引用指向子类对象实例化
- 类实现接口用implements表示
- 接口的子类可以是抽象类(意义不大),也可以是具体类,具体类需要重写接口中所有的抽象方法
接口的成员特点
- 成员变量只能是公共的静态的常量,默认修饰符public static final
- 接口没有构造方法
- 成员方法只能是抽象的,默认修饰符 public abstract
练习代码
public class Demo07_interFance {
public static void main(String[]agrs){
Str s = new stccla();//父类引用指向子类对象
s.print();
System.out.println(Str.num);
}
}
//接口用关键字表示,接口不能实例化,按照多态中父类引用指向子类对象
interface Str {
//接口中的成员变量都是公共的静态的常量,默认修饰符public static final
public static final int num = 20;
//publicmethod(){} 接口中没有构造方法
//接口中成员方法只能是抽象方法,默认修饰符public abstract
public abstract void print();
}
//类实现接口用implements表示
class stccla implements Str{//一个类不继承任何类会默认继承object类
//接口的子类可以是抽象类(意义不大).可以是具体类,需要重写接口中的抽象方法
public void print(){
System.out.println("stccla重写抽象类中抽象方法输出");
}
}
class stcclb implements Str{//一个类不继承任何类会默认继承object类
//接口的子类可以是抽象类(意义不大).可以是具体类,需要重写接口中的抽象方法
public void print(){
System.out.println("stcclb重写抽象类中抽象方法输出");
}
}
输出结果
类与类、接口与接口、类与接口的关系
- 类与类
继承关系:类与类之间可以单继承和多层继承 - 接口与接口
继承关系:接口与接口之间可以单继承和多继承 - 类与接口
实现关系:可以单实现也可以多实现
且可以在继承一个类的同时实现多个接口
练习代码
public class Demo07_interFanceTest {}
interface inter1{}
interface inter2{}
interface inter3 extends inter1,inter2{}//接口和接口之间的关系:可以单继承也可以多继承
class cla1{}
class cla2 extends cla1{}
class cla3 extends cla2{} //类和类之间的关系:可以单继承和多层继承
class cla4 extends cla3 implements inter1,inter2,inter3{}//类和接口的关系:可以单继承一个类或继承一个类的同时实现单个或多个接口,实现单个或多个接口
总结:成员区别
-
抽象类
成员变量:可以是变量也可以是常量
构造方法:有构造方法,用于子类访问父类数据的初始化
成员方法:可以是抽象的,也可以是非抽象的 -
接口
成员变量:只能是常量(public static final修饰)
构造方法:没有
成员方法:只能是抽象的(public abstract修饰)