多态与抽象(被abstract这样的可选关键字修饰)
多态:相同的行为,不同的实现(重载、重写,动态绑定),针对的是动作,方法。
给私有属性添加get set方法的好处:
1.隐藏真实属性的存储方式;
2.给外界提供只读或只写方法;
3.在get/set中还可以提供数据校验。
java编程四个时期:编辑,编译(.java->.class),加载(类加载、字节校验),运行(解释器把.class解释给操作系统)
多态是面向对象编程的精髓所在。
多态分为:静态多态(包括重载、重写,指在编译期即决定要执行的效果),动态多态(在编译期不知道多态的效果,要运行起来后根据绑定
对象的不同,得到不同效果的多态)
动态多态的实现:使用动态绑定和重写实现
动态技术包含的技术基础:转型(等号两边数据类型不一致),instanceof关键字。
不是所有的数据类型都可以转换,像类这样的引用数据类型要强转,必须要有继承关系,Object最大,父类(大类型)大于子类(小类型)
基本数据类型转化成引用数据类型,使用Java包装类的工具类Integer
规则:向上转,是自动的;向下转,是强转的。
例如Persion类分为Man类、Woman类,Persion p=new Man()是自动类型转换,父类引用可以指向子类对象,此时P只能访问Persion中的属性
和方法,而看不到子类特有的部分。
再例如,Man man=(Man)(new Persion()),这是强转的,编译期会通过,但运行失败。
而换成:Persion p=new Man();Man man=(Man)p;就不会出现编译错误,这个时候man确实指向Man类一个Mna对象。
结论:强转不一定成功,只有运行起来后确实指向该子类的一个实例才行。父类的引用指向子类的对象,子类的引用不能指向父类对象,本
类对象指向本类对象。
解决:使用instanceof关键字先做判断。
多态的应用:方法的形参是个引用。
抽象类
被abstract关键字修饰,只用在修饰类和方法上,public abstract 与 abstract public 是一样的。
只要在方法声明中写了{ },就表明该方法被实现了;
抽象类不能实例化产生对象,抽象方法只要方法签名,而没有实现。
当一个类拥有类一个抽象方法时,这个类就不能产生对象,这个类就叫抽象类,需要被abstract关键字修饰。
抽象类只能做父类。可以强制要求子类重写抽象方法。
结论:
1.设计时候,有抽象方法的类才被设计成抽象类。但是,语法上,抽象类里面可以没有抽象方法,不过这样子没有意义。
public abctract claa Test{
abstract type method_name(method_array);
}
2.任何子类必须重写抽象方法,除非该子类也是抽象类。越往上层,抽象的等级越高。
抽象类:
package com.lovo.abs;
public abstract class A {
private int aa;
private String bb;
public A(){
}
public abstract void a();
public abstract void b();
public void c(){
System.out.println("已实现");
}
}
package com.lovo.abs;
public abstract class B extends A{
public void b(){
}
}
package com.lovo.abs;
public class C extends B{
public void a(){
}
}
多态之动态绑定
package com.lovo.game;
public class Role {
public void attack(Weapon weapon){
System.out.println("老子弄你!!!");
weapon.harmEffect();
if(weapon instanceof Sword){
Sword sw = (Sword)weapon;
sw.effectOver();
}
}
}
package com.lovo.game;
public class Spear extends Weapon {
@Override
public void harmEffect() {
// TODO Auto-generated method stub
System.out.println("金枪不倒!!");
}
}
package com.lovo.game;
public class Sword extends Weapon{
@Override
public void harmEffect() {
// TODO Auto-generated method stub
System.out.println("一剑封喉!");
}
public void effectOver(){
System.out.println("收剑入鞘!");
}
}
public class GameTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Role r = new Role();
Spear s = new Spear();
Sword sw = new Sword();
r.attack(sw);
}
}
类型转换(继承关系的引用类型)
父类:
public class PersonBean {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void hello() {
System.out.println("同志,你好!");
}
}
子类A:
package com.lovo.bean;
public class MaleBean extends PersonBean {
private int height;
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public void dance(){
System.out.println("我们爱跳钢管舞!");
}
public void hello() {
System.out.println("Hi,baby!");
}
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
if(obj instanceof MaleBean){
MaleBean m = (MaleBean)obj;
if(this.height == m.getHeight() &&
this.getName().equals(m.getName()) &&
this.getAge() == m.getAge()){
return true;
}else{
return false;
}
}else{
return false;
}
}
}
子类B:
package com.lovo.bean;
public class FemaleBean extends PersonBean {
}
测试:
package com.lovo.test;
import com.lovo.bean.FemaleBean;
import com.lovo.bean.MaleBean;
import com.lovo.bean.PersonBean;
public class TestMain {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
PersonBean p = new PersonBean();
//父类引用指向子类对象,一定成功!
p = new MaleBean();
// p = new FemaleBean();
// MaleBean m = (MaleBean)new PersonBean();
if(p instanceof MaleBean){
//强转不一定成功,必须运行起来以后确实指向该子类对象才能成功
MaleBean m = (MaleBean)p;
p.hello();
m.hello();
}else{
System.out.println("p指向的不是男性对象");
}
}
}