Day09 --面向对象
来源:互联网 发布:多少岁淘宝能贷款 编辑:程序博客网 时间:2024/04/28 03:03
a.
多态
概述
多态就是事物存在的多种形态。即:这只猫挺可爱的,也可以说成这只动物挺可爱的,描述的都是同一种事物。
* 由于参数列表不同,而导致的执行效果不同,这种情况叫做多态。
前提
* 要存在继承关系
* 要有方法的重写,即重写父类中的方法。
* 要有父类引用指向子类对象。
* 也就是说:父类 f = new 子类(); f就是父类引用指向子类对象。因为存在继承关系和方法的重写,所以这种情况可行。
f.eat(); //结果:猫吃鱼,因为子类将父类的方法进行了重写,所以f.eat()调用的是子类中的方法,如果子类中没有这个方法,就调用的是父类中的方法。
特点
多态不仅解决了方法同名的问题,而且还将程序变的更加灵活,从而提高了代码的扩展性和维护性。
例子中的部分关键代码
//Cat c = new Cat(); //new普通的对象 (猫是一只猫)
//c.eat();
Animal a = new Cat(); //父类引用指向子类对象。 (猫是一只动物)
a.eat(); //结果:结果:猫吃鱼,因为子类将父类的方法进行了重写,所以f.eat()调用的是子类中的方法,如果子类中没有这个方法,就调用的是父类中的方法。
例子:
G:\CSDN_Android_\Code\day09 面向对象\01_多态\Demo1_多态的概述.java
b.
多态访问成员的特点 [左边:父类,右边:子类]
多态访问成员的特点 [左边:父类,右边:子类]
1) 成员变量,编译看左,运行也看左。
* 父类中有,就用父类的,即使父类中的成员变量没有被赋值,也调用父类的;
* 因为是父类的引用,所以指向的肯定是父类的成员。当父类中没有该成员时,但子类有,结果报错,因为多态的 "成员变量" 跟子类没关系。
2) 成员方法属于动态绑定! 所以编译看左,运行看右。
3) 静态成员方法属于静态绑定! 所以编译看左,运行也看左。(跟成员变量一样)
* 静态只和类有关,因为静态是随着类的加载而加载的,所以他算不上是重写,所以访问结果还是看左边。
* 只有非静态的方法,编译看左,运行看右。
不满足多态的特征,因为父类中没有该方法,所不能重写父类中的方法,只有重写父类中的方法了,才算编译看左,运行看右。
例子中的部分关键代码
//测试多态中的成员变量 编译看左,运行也看左。
Father f = new Son();
System.out.println(f.name); //结果:哈哈,说明多态中的成员变量是:编译看左,运行也看左。
//System.out.println(f.age); //因为是父类的引用f,所以指向的肯定是父类的成员。当父类中没有该成员时,但子类有,结果报错,因为多态的成员变量跟子类没关系。
//测试多态中的成员方法 编译看左,运行看右。
Father f2 = new Son();
f2.eat(); //结果:子类 嘻嘻 说明多态中的成员方法,编译看左,运行看右。
//因为在编译的时候看左边是否有这个方法,保证左边有的前提下,去看右边子类中是否有,如果子类有,就将子类的方法放入栈内,打印的子类结果。
//如果父类中没有该方法,就运行错误。
//但子类没有重写父类中的方法,结果还是父类的。
//测试多态中的静态成员方法 编译看左,运行也看左。
Father f3 = new Son();
f3.method(); //结果:父类method hehe 静态方法不属于重写,所以就算不上多态情况的一种,但最终还是编译看左,运行也看左。
//相当于是Father.method();
class F{
String name ="哈哈";
public void eat(){
sop("父类 哈哈");
}
public static void method(){
sop("父类method hehe");
}
}
class S extends F{
String name ="嘻嘻";
int age =9;
public void eat(){
sop("子类 嘻嘻");
}
public static void method(){
sop("子类method xixi");
}
}
例子:
G:\CSDN_Android_\Code\day09 面向对象\01_多态\Demo2_多态中的成员访问特点之成员变量_成员方法_静态成员方法.java
c.
多态的向上转型和向下转型
PersonSon p = new SuperMan(); 向上转型 --父类引用指向子类对象
SuperMan s = (SuperMan)p; 向下转型 --将父类变成子类,才能使用子类特有的属性和行为。
StudentFun sf = new StudentFun();
Student s = (Student)sf; //这样的过程就是向下转型。
* 参考以前:
基本数据类型提升 和 强制类型转换
* 基本数据类型
int a=10;
byte b=20;
a = b; //小的可以直接放大里放, 这种情况叫:基本数据类型的自动类型提升。
b = a; //大的给小的,会损失进度,必须强转,即 b=(byte)(a);
* 引用数据类型
* Person父类 SuperMan子类。
1)Person p = new SuperMan(); 这种父类引用指向子类对象叫“向上转型” 即 superMan提升为了Person类型。
2)SuperMan s = (SuperMan)p; 将父类对象强转化为子类对象 这种情况叫:向下转型。
由上可知:
父类引用指向子类对象 叫 向上转型。
将父类对象的强转为子类对象 叫 向下转型。
记住:
必须先有 "向上转型",才能有 "向下转型"。
例子参考:
G:\CSDN_Android_\Code\day09 面向对象\Demo3_使用超人来讲解多态的向上转型和向下转型.java
d.
多态好处和弊端
好处:
* 提高了代码的维护性(继承保证)
* 提高了代码的扩展性(多态保证)[可以将父类当做形式参数,来接收(强转为)任意的子类对象。] public static void method(Aniaml[其实该父类是一个抽象类,后面具体讲] a){}
弊端:
不能直接访问子类特有的属性和行为,必须要靠 “向下转型” 来完成对子类特有属性和行为的访问。
例子代码中的部分关键点:
//Animal2 a = new Cat2() 开发中很少使用父类引用指向子类对象,而是直接使用子类引用去创建子类对象,因为这样可以访问到子类中所有的成员。
//那么什么时候使用多态呢?
//当多态当做为形式参数的时候用最好,因为这种扩展性强,如下。
/**
public static void method(Animal2 a){ //多态提高了代码的扩展性
//a.eat();
//如果将狗强转为猫,就会出现类型转换异常:ClassCastException, 所以做判断来完成具体的子类对象的分析。
//要使用到一个关键字:instanceof 判断前面的引用是否是后面的数据类型或子类。
if(a instanceof Cat2){ //如果动物是一只猫,
Cat2 c = (Cat2)a; //就将动物强转为狗。
c.eat();
c.catchMouse();
}else if(a instanceof Dog2){ //如果动物是一只狗,
Dog2 d = (Dog2)a; //就将动物类强转为狗。
d.eat();
d.lookHome();
}else{
a.eat();
}
}
这种情况很少出现,因为在开发中,想使用谁,直接创建形式参数具体的子类的对象即可。
即:public static void method(Cat2 c){}
main{
method(new Cat2());
}
public static void method(Dog2 d){}
main{
method(new Dog2());
}
*/
例子:
G:\CSDN_Android_\Code\day09 面向对象\01_多态\Demo4_多态好处和弊端.java
e.
多态中的面试题分析
A:看下面程序是否有问题,如果没有,说出结果
class Fu {
//父类补充method方法
public void method() {
System.out.println("fu method");
}
public void show() {
System.out.println("fu show");
}
}
class Zi extends Fu {
public void show() {
System.out.println("zi show");
}
public void method() {
System.out.println("zi method");
}
}
class Test1_多态面试题1 {
public static void main(String[] args) {
Fu f = new Zi();
//f.method(); //结果:错误,因为在父类中没有method方法。
f.show();
//再次抒写
f.method();
}
}
/**
结果:
f.method(); //结果:错误,因为多态中的成员方法 编译看左,运行看右,左边没有父类没有method方法,所以直接报错。
所以:
只需要在父类中添加method方法即可。
public void method() {
System.out.println("fu method");
}
*/
B:看下面程序是否有问题,如果没有,说出结果
class A {
public void show() {
show2(); //我
}
public void show2() {
System.out.println("我");
}
}
class B extends A {
public void show2() {
System.out.println("爱"); //爱
}
}
class C extends B {
public void show() {
super.show(); //爱
}
public void show2() {
System.out.println("你"); // 你
}
}
public class Test2_多态面试题2 {
public static void main(String[] args) {
A a = new B();
a.show(); //爱 因为子类B继承了父类A,父类A中有show()方法,所以相当于子类B也有了show()方法,又因为show方法中调用的是show2()的结果,又因为子类B中存在show2()的方法,即根据编译看左,运行看右的规则,show()中show2()调用的是子类show2()方法,即结果是:爱。
B b = new C();
b.show(); //你 因为子类C继承了父类B,父类B中有show()方法,所以相当于子类C也有了show()方法,因为show方法中调用的是show2()的结果,又因为子类C中存在show2()的方法,即根据编译看左,运行看右的规则,show()中show2()调用的是子类show2()方法,即结果是:你。
}
}
结果: 爱
你
f.
抽象类
概述
抽象的意思是看不懂,在Java中的意思是:表示该类中都是一些没有具体实现过程的方法,连{}都没有。且用abstract(抽象)关键字来修饰。
java中定义没有方法体的方法,该方法由具体的子类来完成,这种方法就叫抽象方法,包含有抽象方法的类就叫抽象类。
特点
0)抽象类中有构造方法,但不能被实例化,只能通过父类引用指向子类对象的方式,即如下:
* Animal a = new Dog(); Animal是抽象类还是Dog的父类,因为抽象所以Animal不能被实例化。 Dog是具体子类。但是可以: 父类引用指向子类对象 的方式来创建对象。
1)抽象类和抽象方法都必须用 abstract 关键字来修饰。
即
public abstract class 类名(){ //抽象类
public abstract void eat(); //没有具体实现的方法,连{}都没有。
public abstract void method(); //没有具体实现的方法,连{}都没有。
}
2)抽象类中不一定要有抽象方法,但有抽象方法的类一定是抽象类或者接口。
3)抽象类不能new,即被实例化,那该怎么用呢?
* 按照多态的方式,由具体的子类去继承该抽象类且完成实例化,其实这也是多态的一种:抽象类多态。
4)抽象类的子类
* 要么是还是抽象类
* 要么是普通类,但要重写抽象类中所有的方法,且方法必须有完善的实现步骤。
抽象方法的由来:
多个对象都具备相同的功能,当功能的具体内容不同,那么在抽取过程中,只抽取了功能定义,未抽取功能主体,那么只有功能声明,没有功能主体的方法就成为抽象方法。
什么时候定义抽象方法
* 当不知道该方法是怎样的实现过程且多个子类都需要这个方法时,可定义为抽象,是抽象方法的都必须放在抽象类中。
为什么不能实例化抽象类
* 因为实例化的类,都要去使用里面具体的方法,但抽象类中的方法都是抽象的没有其实现过程,去调用该方法没有什么意义。
不可以去实例化抽象类,但可以去声明抽象类,即:父类引用指向子类对象。
Animal a = new Cat(); //该Animal是抽象类,因为多态的成员方法是:编译看左(左边即父类,有该方法不管是否是抽象方法或普通方法),运行看右(右边即子类,调用是子类具体的方法)。
c.eat();
例子:
G:\CSDN_Android_\Code\day09 面向对象\02_抽象类\Demo1_abstract_抽象类的概述及其特点.java
g.
抽象类的成员特点
1)抽象类中成员变量的特点:
* 成员变量:既可以是变量,也能是常量。但都不能被抽象。
* abstract是否能修饰成员变量? 不能被修饰成员变量。
* 是否有构造方法? 有构造方法,是用来给子类进行初始化用的。
* 成员方法:既可以是抽象的(但强制要求子类重写该方法),也可以不是抽象的(用来继承,提供代码维护性[子类继承该抽象类,就能直接调用该非抽象方法])
2)抽象类中成员方法的特点:
* 抽象方法,强制要求子类要做的事情。
* 非抽象方法,子类继承的事情,提高代码的维护性[子类继承抽象类后,就可以直接使用该非抽象方法]。
为什么要普通类去继承抽象类呢?
* 因为工作中 遵守规则,方便开会后制定标准:统一规则,合作开发用的。
p.s.
抽象类中是否有构造函数?
有,用于给子类对象进行初始化的。
抽象类中可不可以没有抽象方法?
可以,目的是让该类创建对象。
p.s.
抽象类和一般类的区别?
相同点:
都是用来描述事物,都在内部定义了成员。
异同点:
一般类有足够的信息来描述事物。
抽象类描述事物信息可能有些不足。
一般类中没有抽象方法,只能定义非抽象方法。
抽象类中可以定义抽象方法,同时也能定义非抽象方法。
一般类可以被实例化。
抽象类不可以被是实例化。
抽象类可以是一个父类吗?
是的,因为子类需要覆盖里面的方法,才能对子类进行实例化。
例子:
G:\CSDN_Android_\Code\day09 面向对象\02_抽象类\Demo2_abstract_抽象类的成员特点.java
h.
抽象类的作用
葵花宝典案例
例子:G:\CSDN_Android_\Code\day09 面向对象\02_抽象类\Demo3_abstract_葵花宝典的方式讲解抽象类的使用.java
i.
抽象类练习题
猫狗案例
* A:案例演示
* 具体事物:猫,狗
* 共性:姓名,年龄,吃饭
* 猫的特性:抓老鼠
* 狗的特性:看家
例子: G:\CSDN_Android_\Code\day09 面向对象\02_抽象类\Test1_abstract_抽象类练习猫狗案例.java
老师案例
A:案例演示
* 具体事物:基础班老师,就业班老师
* 共性:姓名,年龄,讲课。
* 具体事物:基础班学生,就业班学生
* 共性:姓名,年龄,学习
例子:G:\CSDN_Android_\Code\day09 面向对象\02_抽象类\Test2_abstract_抽象类练习老师案例.java
员工案例
A:案例演示
* 假如我们在开发一个系统时需要对程序员类进行设计,程序员包含3个属性:姓名、工号以及工资。
* 经理,除了含有程序员的属性外,另为还有一个奖金属性。
* 请使用继承的思想设计出程序员类和经理类。要求类中提供必要的方法进行属性访问。
例子:G:\CSDN_Android_\Code\day09 面向对象\02_抽象类\ziCat.class
g.
抽象类中面试题
A:面试题1
* 一个抽象类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
* 可以。意义在于 不让其他类去创建本类对象,而是让其子类去创建对象。
* B:面试题2
* abstract【不能】和哪些关键字共存 3个
* private 如果定义为私有方法,子类就无法重写父类中抽象方法,但被abstract修饰的方法,必须要求子类去重写,所以不可以。
* static 如果定义为静态,就可以直接类名.方法名()去调用, 但抽象类中的方法都是没有方法体的,所以这样没意义。
* final 如果定义为final,该方法变成最终,不能被子类重写,但被abstract修饰的方法,必须要求子类对其父类中方法进行重写,发生冲突,所以抽象也不可以跟final共存。
* abstract【能】和哪些关键字共存
* public
* public abstract
* interface
h.
接口
概述
抽象类中可定义接口或普通方法,而在接口中全部都是抽象方法,用于对外提供规则的都是接口。
一个抽象类中的方法都是抽象的时候,可以将该抽象类以另一种的形式来表示:即接口。
特点
* 用 interface 来修饰
* interface 接口{ }
* 子类用 implements 来去实现,Java中是单继承,多实现的。
* class 类名 implement 接口名, 接口名{}
* 接口能被实例化吗?,
* 不能实例化,因为接口中方法都没有方法体,这样做没意义,所以只能通过多态的方式去实现实例化。
* 多态方式: 接口 接口名 = new 普通类();
* 接口的子类:
* 要么是抽象类,没意义。
* 要么是具体类,但必须要重写接口中所有的抽象方法。(推荐使用)
p.s.
接口中的成员修饰符都是固定的:
成员常量: public static final
成员方法: public abstract
由此可见,接口中的成员都是公共的修饰权限。
接口是对外暴露的规则。
接口是程序的功能扩展。
p.s.
java中不直接支持多继承,因为会出现调用的不稳定性。
所以java将多继承机制进行改良,在java中变成了多实现,一个类可以实现多个接口,接口的出现避免了单继承的局限性。
体现:
父类或接口中的引用指向或接收了直接子类的对象。
作用:
多态的存在,提供了程序的扩展性和后期可维护性。
前提:
必须存在继承或实现关系。
需要有覆盖即重写的动作。
好处:
提供了代码扩展性,前期定义了代码可以使用后期的内容。
弊端:
前期定义的内容不能调用后期子类特有的内容。
例子:G:\CSDN_Android_\Code\day09 面向对象\03_接口\Demo1_instance接口概述.java
接口中成员特点
成员变量:
* 只能是常量(抽象类中可是常量也能是变量),且必须是公共静态最终的。
* 默认修饰符: public static final int NUM = 7;
* 建议手动给出。
构造方法:
* 接口中没有构造方法
成员方法:
* 接口中只能是抽象方法且没有方法体的。
* 默认: public abstract void method();
* 建议手动给出。
例子:G:\CSDN_Android_\Code\day09 面向对象\03_接口\Demo2_interface_成员特点.java
接口与类之间的关系
* 类与类
* 只能是继承关系,而且只能是单继承,但可以多实现。
* 接口与类
* 实现关系,可单实现,也可多实现,且一个类可以实现多个接口。
* 接口与接口
* 继承关系,可以单继承,也可多继承。(一个接口可以继承多个接口)
例子:G:\CSDN_Android_\Code\day09 面向对象\03_接口\Demo3_接口与类的关系.java
抽象类与接口区别
1)成员区别
* 抽象类:
* 成员变量:可以是常量,也能是变量。
* 构造方法:有,用于给子类初始化用的。
* 成员方法:既可以是抽象的(子类继承后必须重写该方法),也能是非抽象的(子类继承后直接使用该方法)。
* 接口
* 成员变量:只能是常量,默认 public static final 修饰。
* 构造方法:没有
* 成员方法:只能是抽象的,默认 public abstract 修饰。
2)关系区别
* 类与类
* 继承,且单继承
* 类与接口
* 实现,可单实现,也能多实现
* 接口与接口
* 继承,可单继承,也能能多继承
3)设计理念区别
* 抽象类:
* 被继承的关系, 体现的是一种 “is a” 的关系,抽象类中定义的是该继承体现的共性功能,即 猫 是 动物 的一种关系。动物就是共性功能。
* 接口
* 被实现的关系, 体现的是一种 “like a” 的关系,接口中定义的是该继承体系的扩展功能, 即 金毛看起来 像 狗 的一种关系。 金毛就是扩展功能。
p.s.
抽象类和接口的异同:
相同:
都是不断向上抽象而来的。
异同:
1) 抽象类是要被继承的,且是单继承。
接口是需要被实现的,可以多实现。
2) 抽象类中可以定义抽象方法和非抽象方法,子类继承后,要将抽象方法进行重写,但可以直接使用非抽象方法。
接口中只能定义抽象方法,但必须要由子类去实现。
3) 抽象类的继承,是 is a的关系,定义了继承该体系的基本共性内容,
接口的实现是 like a 的关系, 定义了该继承体现的扩展功能。
猫狗案例加入跳高功能分析及其代码实现
* A:案例演示
* 动物类:姓名,年龄,吃饭,睡觉。
* 猫和狗
* 动物培训接口:跳高
例子:G:\CSDN_Android_\Code\day09 面向对象\03_接口\Test1_猫狗案例.java
多态
概述
多态就是事物存在的多种形态。即:这只猫挺可爱的,也可以说成这只动物挺可爱的,描述的都是同一种事物。
* 由于参数列表不同,而导致的执行效果不同,这种情况叫做多态。
前提
* 要存在继承关系
* 要有方法的重写,即重写父类中的方法。
* 要有父类引用指向子类对象。
* 也就是说:父类 f = new 子类(); f就是父类引用指向子类对象。因为存在继承关系和方法的重写,所以这种情况可行。
f.eat(); //结果:猫吃鱼,因为子类将父类的方法进行了重写,所以f.eat()调用的是子类中的方法,如果子类中没有这个方法,就调用的是父类中的方法。
特点
多态不仅解决了方法同名的问题,而且还将程序变的更加灵活,从而提高了代码的扩展性和维护性。
例子中的部分关键代码
//Cat c = new Cat(); //new普通的对象 (猫是一只猫)
//c.eat();
Animal a = new Cat(); //父类引用指向子类对象。 (猫是一只动物)
a.eat(); //结果:结果:猫吃鱼,因为子类将父类的方法进行了重写,所以f.eat()调用的是子类中的方法,如果子类中没有这个方法,就调用的是父类中的方法。
例子:
G:\CSDN_Android_\Code\day09 面向对象\01_多态\Demo1_多态的概述.java
b.
多态访问成员的特点 [左边:父类,右边:子类]
多态访问成员的特点 [左边:父类,右边:子类]
1) 成员变量,编译看左,运行也看左。
* 父类中有,就用父类的,即使父类中的成员变量没有被赋值,也调用父类的;
* 因为是父类的引用,所以指向的肯定是父类的成员。当父类中没有该成员时,但子类有,结果报错,因为多态的 "成员变量" 跟子类没关系。
2) 成员方法属于动态绑定! 所以编译看左,运行看右。
3) 静态成员方法属于静态绑定! 所以编译看左,运行也看左。(跟成员变量一样)
* 静态只和类有关,因为静态是随着类的加载而加载的,所以他算不上是重写,所以访问结果还是看左边。
* 只有非静态的方法,编译看左,运行看右。
不满足多态的特征,因为父类中没有该方法,所不能重写父类中的方法,只有重写父类中的方法了,才算编译看左,运行看右。
例子中的部分关键代码
//测试多态中的成员变量 编译看左,运行也看左。
Father f = new Son();
System.out.println(f.name); //结果:哈哈,说明多态中的成员变量是:编译看左,运行也看左。
//System.out.println(f.age); //因为是父类的引用f,所以指向的肯定是父类的成员。当父类中没有该成员时,但子类有,结果报错,因为多态的成员变量跟子类没关系。
//测试多态中的成员方法 编译看左,运行看右。
Father f2 = new Son();
f2.eat(); //结果:子类 嘻嘻 说明多态中的成员方法,编译看左,运行看右。
//因为在编译的时候看左边是否有这个方法,保证左边有的前提下,去看右边子类中是否有,如果子类有,就将子类的方法放入栈内,打印的子类结果。
//如果父类中没有该方法,就运行错误。
//但子类没有重写父类中的方法,结果还是父类的。
//测试多态中的静态成员方法 编译看左,运行也看左。
Father f3 = new Son();
f3.method(); //结果:父类method hehe 静态方法不属于重写,所以就算不上多态情况的一种,但最终还是编译看左,运行也看左。
//相当于是Father.method();
class F{
String name ="哈哈";
public void eat(){
sop("父类 哈哈");
}
public static void method(){
sop("父类method hehe");
}
}
class S extends F{
String name ="嘻嘻";
int age =9;
public void eat(){
sop("子类 嘻嘻");
}
public static void method(){
sop("子类method xixi");
}
}
例子:
G:\CSDN_Android_\Code\day09 面向对象\01_多态\Demo2_多态中的成员访问特点之成员变量_成员方法_静态成员方法.java
c.
多态的向上转型和向下转型
PersonSon p = new SuperMan(); 向上转型 --父类引用指向子类对象
SuperMan s = (SuperMan)p; 向下转型 --将父类变成子类,才能使用子类特有的属性和行为。
StudentFun sf = new StudentFun();
Student s = (Student)sf; //这样的过程就是向下转型。
* 参考以前:
基本数据类型提升 和 强制类型转换
* 基本数据类型
int a=10;
byte b=20;
a = b; //小的可以直接放大里放, 这种情况叫:基本数据类型的自动类型提升。
b = a; //大的给小的,会损失进度,必须强转,即 b=(byte)(a);
* 引用数据类型
* Person父类 SuperMan子类。
1)Person p = new SuperMan(); 这种父类引用指向子类对象叫“向上转型” 即 superMan提升为了Person类型。
2)SuperMan s = (SuperMan)p; 将父类对象强转化为子类对象 这种情况叫:向下转型。
由上可知:
父类引用指向子类对象 叫 向上转型。
将父类对象的强转为子类对象 叫 向下转型。
记住:
必须先有 "向上转型",才能有 "向下转型"。
例子参考:
G:\CSDN_Android_\Code\day09 面向对象\Demo3_使用超人来讲解多态的向上转型和向下转型.java
d.
多态好处和弊端
好处:
* 提高了代码的维护性(继承保证)
* 提高了代码的扩展性(多态保证)[可以将父类当做形式参数,来接收(强转为)任意的子类对象。] public static void method(Aniaml[其实该父类是一个抽象类,后面具体讲] a){}
弊端:
不能直接访问子类特有的属性和行为,必须要靠 “向下转型” 来完成对子类特有属性和行为的访问。
例子代码中的部分关键点:
//Animal2 a = new Cat2() 开发中很少使用父类引用指向子类对象,而是直接使用子类引用去创建子类对象,因为这样可以访问到子类中所有的成员。
//那么什么时候使用多态呢?
//当多态当做为形式参数的时候用最好,因为这种扩展性强,如下。
/**
public static void method(Animal2 a){ //多态提高了代码的扩展性
//a.eat();
//如果将狗强转为猫,就会出现类型转换异常:ClassCastException, 所以做判断来完成具体的子类对象的分析。
//要使用到一个关键字:instanceof 判断前面的引用是否是后面的数据类型或子类。
if(a instanceof Cat2){ //如果动物是一只猫,
Cat2 c = (Cat2)a; //就将动物强转为狗。
c.eat();
c.catchMouse();
}else if(a instanceof Dog2){ //如果动物是一只狗,
Dog2 d = (Dog2)a; //就将动物类强转为狗。
d.eat();
d.lookHome();
}else{
a.eat();
}
}
这种情况很少出现,因为在开发中,想使用谁,直接创建形式参数具体的子类的对象即可。
即:public static void method(Cat2 c){}
main{
method(new Cat2());
}
public static void method(Dog2 d){}
main{
method(new Dog2());
}
*/
例子:
G:\CSDN_Android_\Code\day09 面向对象\01_多态\Demo4_多态好处和弊端.java
e.
多态中的面试题分析
A:看下面程序是否有问题,如果没有,说出结果
class Fu {
//父类补充method方法
public void method() {
System.out.println("fu method");
}
public void show() {
System.out.println("fu show");
}
}
class Zi extends Fu {
public void show() {
System.out.println("zi show");
}
public void method() {
System.out.println("zi method");
}
}
class Test1_多态面试题1 {
public static void main(String[] args) {
Fu f = new Zi();
//f.method(); //结果:错误,因为在父类中没有method方法。
f.show();
//再次抒写
f.method();
}
}
/**
结果:
f.method(); //结果:错误,因为多态中的成员方法 编译看左,运行看右,左边没有父类没有method方法,所以直接报错。
所以:
只需要在父类中添加method方法即可。
public void method() {
System.out.println("fu method");
}
*/
B:看下面程序是否有问题,如果没有,说出结果
class A {
public void show() {
show2(); //我
}
public void show2() {
System.out.println("我");
}
}
class B extends A {
public void show2() {
System.out.println("爱"); //爱
}
}
class C extends B {
public void show() {
super.show(); //爱
}
public void show2() {
System.out.println("你"); // 你
}
}
public class Test2_多态面试题2 {
public static void main(String[] args) {
A a = new B();
a.show(); //爱 因为子类B继承了父类A,父类A中有show()方法,所以相当于子类B也有了show()方法,又因为show方法中调用的是show2()的结果,又因为子类B中存在show2()的方法,即根据编译看左,运行看右的规则,show()中show2()调用的是子类show2()方法,即结果是:爱。
B b = new C();
b.show(); //你 因为子类C继承了父类B,父类B中有show()方法,所以相当于子类C也有了show()方法,因为show方法中调用的是show2()的结果,又因为子类C中存在show2()的方法,即根据编译看左,运行看右的规则,show()中show2()调用的是子类show2()方法,即结果是:你。
}
}
结果: 爱
你
f.
抽象类
概述
抽象的意思是看不懂,在Java中的意思是:表示该类中都是一些没有具体实现过程的方法,连{}都没有。且用abstract(抽象)关键字来修饰。
java中定义没有方法体的方法,该方法由具体的子类来完成,这种方法就叫抽象方法,包含有抽象方法的类就叫抽象类。
特点
0)抽象类中有构造方法,但不能被实例化,只能通过父类引用指向子类对象的方式,即如下:
* Animal a = new Dog(); Animal是抽象类还是Dog的父类,因为抽象所以Animal不能被实例化。 Dog是具体子类。但是可以: 父类引用指向子类对象 的方式来创建对象。
1)抽象类和抽象方法都必须用 abstract 关键字来修饰。
即
public abstract class 类名(){ //抽象类
public abstract void eat(); //没有具体实现的方法,连{}都没有。
public abstract void method(); //没有具体实现的方法,连{}都没有。
}
2)抽象类中不一定要有抽象方法,但有抽象方法的类一定是抽象类或者接口。
3)抽象类不能new,即被实例化,那该怎么用呢?
* 按照多态的方式,由具体的子类去继承该抽象类且完成实例化,其实这也是多态的一种:抽象类多态。
4)抽象类的子类
* 要么是还是抽象类
* 要么是普通类,但要重写抽象类中所有的方法,且方法必须有完善的实现步骤。
抽象方法的由来:
多个对象都具备相同的功能,当功能的具体内容不同,那么在抽取过程中,只抽取了功能定义,未抽取功能主体,那么只有功能声明,没有功能主体的方法就成为抽象方法。
什么时候定义抽象方法
* 当不知道该方法是怎样的实现过程且多个子类都需要这个方法时,可定义为抽象,是抽象方法的都必须放在抽象类中。
为什么不能实例化抽象类
* 因为实例化的类,都要去使用里面具体的方法,但抽象类中的方法都是抽象的没有其实现过程,去调用该方法没有什么意义。
不可以去实例化抽象类,但可以去声明抽象类,即:父类引用指向子类对象。
Animal a = new Cat(); //该Animal是抽象类,因为多态的成员方法是:编译看左(左边即父类,有该方法不管是否是抽象方法或普通方法),运行看右(右边即子类,调用是子类具体的方法)。
c.eat();
例子:
G:\CSDN_Android_\Code\day09 面向对象\02_抽象类\Demo1_abstract_抽象类的概述及其特点.java
g.
抽象类的成员特点
1)抽象类中成员变量的特点:
* 成员变量:既可以是变量,也能是常量。但都不能被抽象。
* abstract是否能修饰成员变量? 不能被修饰成员变量。
* 是否有构造方法? 有构造方法,是用来给子类进行初始化用的。
* 成员方法:既可以是抽象的(但强制要求子类重写该方法),也可以不是抽象的(用来继承,提供代码维护性[子类继承该抽象类,就能直接调用该非抽象方法])
2)抽象类中成员方法的特点:
* 抽象方法,强制要求子类要做的事情。
* 非抽象方法,子类继承的事情,提高代码的维护性[子类继承抽象类后,就可以直接使用该非抽象方法]。
为什么要普通类去继承抽象类呢?
* 因为工作中 遵守规则,方便开会后制定标准:统一规则,合作开发用的。
p.s.
抽象类中是否有构造函数?
有,用于给子类对象进行初始化的。
抽象类中可不可以没有抽象方法?
可以,目的是让该类创建对象。
p.s.
抽象类和一般类的区别?
相同点:
都是用来描述事物,都在内部定义了成员。
异同点:
一般类有足够的信息来描述事物。
抽象类描述事物信息可能有些不足。
一般类中没有抽象方法,只能定义非抽象方法。
抽象类中可以定义抽象方法,同时也能定义非抽象方法。
一般类可以被实例化。
抽象类不可以被是实例化。
抽象类可以是一个父类吗?
是的,因为子类需要覆盖里面的方法,才能对子类进行实例化。
例子:
G:\CSDN_Android_\Code\day09 面向对象\02_抽象类\Demo2_abstract_抽象类的成员特点.java
h.
抽象类的作用
葵花宝典案例
例子:G:\CSDN_Android_\Code\day09 面向对象\02_抽象类\Demo3_abstract_葵花宝典的方式讲解抽象类的使用.java
i.
抽象类练习题
猫狗案例
* A:案例演示
* 具体事物:猫,狗
* 共性:姓名,年龄,吃饭
* 猫的特性:抓老鼠
* 狗的特性:看家
例子: G:\CSDN_Android_\Code\day09 面向对象\02_抽象类\Test1_abstract_抽象类练习猫狗案例.java
老师案例
A:案例演示
* 具体事物:基础班老师,就业班老师
* 共性:姓名,年龄,讲课。
* 具体事物:基础班学生,就业班学生
* 共性:姓名,年龄,学习
例子:G:\CSDN_Android_\Code\day09 面向对象\02_抽象类\Test2_abstract_抽象类练习老师案例.java
员工案例
A:案例演示
* 假如我们在开发一个系统时需要对程序员类进行设计,程序员包含3个属性:姓名、工号以及工资。
* 经理,除了含有程序员的属性外,另为还有一个奖金属性。
* 请使用继承的思想设计出程序员类和经理类。要求类中提供必要的方法进行属性访问。
例子:G:\CSDN_Android_\Code\day09 面向对象\02_抽象类\ziCat.class
g.
抽象类中面试题
A:面试题1
* 一个抽象类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
* 可以。意义在于 不让其他类去创建本类对象,而是让其子类去创建对象。
* B:面试题2
* abstract【不能】和哪些关键字共存 3个
* private 如果定义为私有方法,子类就无法重写父类中抽象方法,但被abstract修饰的方法,必须要求子类去重写,所以不可以。
* static 如果定义为静态,就可以直接类名.方法名()去调用, 但抽象类中的方法都是没有方法体的,所以这样没意义。
* final 如果定义为final,该方法变成最终,不能被子类重写,但被abstract修饰的方法,必须要求子类对其父类中方法进行重写,发生冲突,所以抽象也不可以跟final共存。
* abstract【能】和哪些关键字共存
* public
* public abstract
* interface
h.
接口
概述
抽象类中可定义接口或普通方法,而在接口中全部都是抽象方法,用于对外提供规则的都是接口。
一个抽象类中的方法都是抽象的时候,可以将该抽象类以另一种的形式来表示:即接口。
特点
* 用 interface 来修饰
* interface 接口{ }
* 子类用 implements 来去实现,Java中是单继承,多实现的。
* class 类名 implement 接口名, 接口名{}
* 接口能被实例化吗?,
* 不能实例化,因为接口中方法都没有方法体,这样做没意义,所以只能通过多态的方式去实现实例化。
* 多态方式: 接口 接口名 = new 普通类();
* 接口的子类:
* 要么是抽象类,没意义。
* 要么是具体类,但必须要重写接口中所有的抽象方法。(推荐使用)
p.s.
接口中的成员修饰符都是固定的:
成员常量: public static final
成员方法: public abstract
由此可见,接口中的成员都是公共的修饰权限。
接口是对外暴露的规则。
接口是程序的功能扩展。
p.s.
java中不直接支持多继承,因为会出现调用的不稳定性。
所以java将多继承机制进行改良,在java中变成了多实现,一个类可以实现多个接口,接口的出现避免了单继承的局限性。
体现:
父类或接口中的引用指向或接收了直接子类的对象。
作用:
多态的存在,提供了程序的扩展性和后期可维护性。
前提:
必须存在继承或实现关系。
需要有覆盖即重写的动作。
好处:
提供了代码扩展性,前期定义了代码可以使用后期的内容。
弊端:
前期定义的内容不能调用后期子类特有的内容。
例子:G:\CSDN_Android_\Code\day09 面向对象\03_接口\Demo1_instance接口概述.java
接口中成员特点
成员变量:
* 只能是常量(抽象类中可是常量也能是变量),且必须是公共静态最终的。
* 默认修饰符: public static final int NUM = 7;
* 建议手动给出。
构造方法:
* 接口中没有构造方法
成员方法:
* 接口中只能是抽象方法且没有方法体的。
* 默认: public abstract void method();
* 建议手动给出。
例子:G:\CSDN_Android_\Code\day09 面向对象\03_接口\Demo2_interface_成员特点.java
接口与类之间的关系
* 类与类
* 只能是继承关系,而且只能是单继承,但可以多实现。
* 接口与类
* 实现关系,可单实现,也可多实现,且一个类可以实现多个接口。
* 接口与接口
* 继承关系,可以单继承,也可多继承。(一个接口可以继承多个接口)
例子:G:\CSDN_Android_\Code\day09 面向对象\03_接口\Demo3_接口与类的关系.java
抽象类与接口区别
1)成员区别
* 抽象类:
* 成员变量:可以是常量,也能是变量。
* 构造方法:有,用于给子类初始化用的。
* 成员方法:既可以是抽象的(子类继承后必须重写该方法),也能是非抽象的(子类继承后直接使用该方法)。
* 接口
* 成员变量:只能是常量,默认 public static final 修饰。
* 构造方法:没有
* 成员方法:只能是抽象的,默认 public abstract 修饰。
2)关系区别
* 类与类
* 继承,且单继承
* 类与接口
* 实现,可单实现,也能多实现
* 接口与接口
* 继承,可单继承,也能能多继承
3)设计理念区别
* 抽象类:
* 被继承的关系, 体现的是一种 “is a” 的关系,抽象类中定义的是该继承体现的共性功能,即 猫 是 动物 的一种关系。动物就是共性功能。
* 接口
* 被实现的关系, 体现的是一种 “like a” 的关系,接口中定义的是该继承体系的扩展功能, 即 金毛看起来 像 狗 的一种关系。 金毛就是扩展功能。
p.s.
抽象类和接口的异同:
相同:
都是不断向上抽象而来的。
异同:
1) 抽象类是要被继承的,且是单继承。
接口是需要被实现的,可以多实现。
2) 抽象类中可以定义抽象方法和非抽象方法,子类继承后,要将抽象方法进行重写,但可以直接使用非抽象方法。
接口中只能定义抽象方法,但必须要由子类去实现。
3) 抽象类的继承,是 is a的关系,定义了继承该体系的基本共性内容,
接口的实现是 like a 的关系, 定义了该继承体现的扩展功能。
猫狗案例加入跳高功能分析及其代码实现
* A:案例演示
* 动物类:姓名,年龄,吃饭,睡觉。
* 猫和狗
* 动物培训接口:跳高
例子:G:\CSDN_Android_\Code\day09 面向对象\03_接口\Test1_猫狗案例.java
阅读全文
0 0
- day09-面向对象
- day09<面向对象+>
- Day09 --面向对象
- 黑马程序员-Java面向对象-day09
- 黑马程序员-day09-面向对象(内部类)
- JAVASE基础-day09(面向对象)
- java入门一DAY09------java 面向对象全面总结
- 面向对象 (多态)+JAVA学习笔记-DAY09
- day09
- day09
- day09
- day09
- day09
- day09
- day09
- day09
- day09
- day09
- [Leetcode] 541. Reverse String II 解题报告
- 后端接口的幂等性
- 模板-最短路//spfa
- 剑指Offer-7:重建二叉树
- strlen和sizeof的区别
- Day09 --面向对象
- 精通Excel数据统计与分析
- 解决AndroidStudio导入项目在 Building gradle project info 一直卡住
- 字符游戏-智能蛇
- 哈夫曼树的生成及哈夫曼编码
- 第15周项目4
- leetcode:739. Daily Temperatures 单调栈
- IT行业风险投资
- MySQL存储引擎--MyISAM与InnoDB区别