多态(面向对象之一) :函数本身就具备多态性,某一种事物有不同的具体的体现。
体现:父类引用或者接口的引用指向了自己的子类对象。//Animal a = new Cat();父类可以调用子类中覆写过的(父类中有的方法)
多态的好处:提高了程序的扩展性。继承的父类或接口一般是类库中的东西,(如果要修改某个方法的具体实现方式)只有通过子类去覆写要改变的某一个方法,这样在通过将父类的应用指向子类的实例去调用覆写过的方法就行了!
多态的弊端:当父类引用指向子类对象时,虽然提高了扩展性,但是只能访问父类中具备的方法,不可以访问子类中特有的方法。(前期不能使用后期产生的功能,即访问的局限性)
多态的前提:
1:必须要有关系,比如继承、或者实现。
2:通常会有覆盖操作。
多态的出现思想上也做着变化:以前是创建对象并指挥对象做事情。有了多态以后,我们可以找到对象的共性类型,直接操作共性类型做事情即可,这样可以指挥一批对象做事情,即通过操作父类或接口实现。 -------------------------------------------------------------- class 毕姥爷{ void 讲课(){ System.out.println("企业管理"); } void 钓鱼(){ System.out.println("钓鱼"); } } class 毕老师 extends 毕姥爷{ void 讲课(){ System.out.println("JAVA"); } void 看电影(){ System.out.println("看电影"); } } class { public static void main(String[] args) { 毕姥爷 x = new 毕老师(); //毕老师对象被提升为了毕姥爷类型。 // x.讲课(); // x.看电影(); //错误. 毕老师 y = (毕老师)x; //将毕姥爷类型强制转换成毕老师类型。 y.看电影();//在多态中,自始自终都是子类对象在做着类型的变化。 } }
如果想用子类对象的特有方法,如何判断对象是哪个具体的子类类型呢?
可以可以通过一个关键字 instanceof ;//判断对象是否实现了指定的接口或继承了指定的类
格式:<对象 instanceof 类型> ,判断一个对象是否所属于指定的类型。
Student instanceof Person = true;//student继承了person类
多态之间的调用,类型转换问题~
/* 怎样可以使用子类中独有的方法 引用类型转换问题 1.自动转换(向上转型) Animal a=new Cat(); a是Animal类型 new Cat()是Cat类型 将Cat类型的值赋给了Animal类型 其实就是向上转换型,原来是子类类型,向上转换成父类类型 这种转换型可以存在的条件必须存在(继承,实现) 2.强制转换(向下转型) Animal a=new Cat(); a是父类的类型, 不可以直接调用子类中独有的行为, 那么想要调用,可以将a向下转换型(将其强制转换成子类类型) 无论是自动还是强制转换必须有前提条件:这种转换型可以存在的条件必须存在(继承,实现) 为什么向下转换:想要调用子类中独有的方法. */ class Demo1 { public static void main(String[] args){ //Animal a=new Cat();//父类引用指向子类对象 /* 多态存在只能使用的是父类中存在,子类中重写的方法 编译时看等号左边 执行时看等号的右边 */ Animal a=new Cat(); a.eat();//调用Cat类中重写的eat方法 Cat cat=(Cat)a; //强制将父类引用转换成子类的引用,向下转型 /* 我们在开发中,如果使用向下转型, 必须保证a这个引用指向的对象的真实类型是Cat类型。 */ cat.catchMouse();//调用Cat类中的独有的方法 } } abstract class Animal { public abstract void eat(); } class Cat extends Animal { public void eat(){ System.out.println("猫吃鱼"); } //猫抓耗子 public void catchMouse(){ System.out.println("猫抓耗子"); } } class Dog extends Animal { public void eat(){ System.out.println("狗吃骨头"); } }
多态实践,设计模式之模板模式
/* 需求 要求设计悍马模型 提供一些基本功能 start点火 stop 停止 引擎转动 行驶这些行为 H1 H3 分析,对于这两种类型在细节上执行可以存在不同,那么我们在设计模型时,细节上就不设计, 只规定其存在这样的行为 在代码中发现H1,H3类中的run方法执行内容一致,那么可以将其向上抽取, 在父类中将run方法实现,这样即避免的对外暴露太多行为,也提高了代码的复用性。 我们在设计这个模型时发现 start点火 stop 停止 引擎转动这三个行为是变化的,需要由具体子类 来实现,行驶这个行为是固定,所有子类中都一样。我们可以在父类中定义,将其实现,直正执行时, 还是去执行具体的子类中的行为. 这种方式也是设计模式中的一种,模板方法模式. */ class Demo2 { public static void main(String[] args) { HM h=new H3(); //多态 h.run(); //调用时调用的H3中的run } } //创建悍马模型 abstract class HM { //打火 abstract void start(); //停止 abstract void stop(); //引擎转动 abstract void yinQingBoom(); //行驶 void run(){ //真正调用时还时执行子类中的重写的方法 this.start(); this.yinQingBoom(); this.stop(); } } class H1 extends HM { //打火 void start(){ System.out.println("H1 打火"); } //停止 void stop(){ System.out.println("H1 停止"); } //引擎转动 void yinQingBoom(){ System.out.println("H1 引擎转动"); } } class H3 extends HM { //打火 void start(){ System.out.println("H3 打火"); } //停止 void stop(){ System.out.println("H3 停止"); } //引擎转动 void yinQingBoom(){ System.out.println("H3 引擎转动"); } }
多态面试
/* 关于多态 面试题 */ class Demo3 { public static void main(String[] args) { Father son=new Son(); //多态 son.method();//调用方法时看等号的右边 } } class Father { private void show(){ /* 如果是private,执行时结果是父类中的show方法 如果是非private 执行结果是子类中的show方法. */ System.out.println("father show"); } public void method(){ this.show(); } } class Son extends Father { public void show(){ System.out.println("son show"); } }
多态应用之锦囊妙计
/* 锦囊妙计 诸葛亮给赵云三个锦囊,里面有三条妙计 1.孙权要杀刘备 找乔国老帮忙。让吴国泰给孙权施加压力 2.让吴国泰帮助,开绿灯放他们走 3.找孙夫人断后,拦截追兵 分析: 1.有三条妙计 可以向上抽取成妙计 2.需要锦囊 其中装的是妙计,是那个妙计不知道 3.当打开锦囊要执行妙计时,需要的是真正的妙计,而不是我们定义的接口。 */ //Demo4想像成赵云 class Demo4 { public static void main(String[] args) { //遇到第一个问题 //MiaoJi m1=new MiaoJi_1(); //System.out.print(m1.operation()); //妙计是放在锦囊中的 JinNang jn=new JinNang(); System.out.println("刚到吴国"); jn.content(new MiaoJi_1()); System.out.println("谈判过程中"); jn.content(new MiaoJi_2()); System.out.println("离开时"); jn.content(new MiaoJi_3()); } } interface MiaoJi { //妙计执行 void operation(); } class MiaoJi_1 implements MiaoJi { public void operation(){ System.out.println("孙权要杀刘备 找乔国老帮忙。让吴国泰给孙权施加压力"); } } class MiaoJi_2 implements MiaoJi { public void operation(){ System.out.println("让吴国泰帮助,开绿灯放他们走"); } } class MiaoJi_3 implements MiaoJi { public void operation(){ System.out.println("找孙夫人断后,拦截追兵"); } } //锦囊 里面装着妙计 class JinNang{ //MiaoJI mj=new MiaoJi_3(); public void content(MiaoJi mj){//定义的是接口类型 //打开锦囊执行妙计 mj.operation(); //调用方法时执行的还是实现类中的方法 } }
多态实践
/* 锦囊妙计 诸葛亮给赵云三个锦囊,里面有三条妙计 1.孙权要杀刘备 找乔国老帮忙。让吴国泰给孙权施加压力 2.让吴国泰帮助,开绿灯放他们走 3.找孙夫人断后,拦截追兵 分析: 1.有三条妙计 可以向上抽取成妙计 2.需要锦囊 其中装的是妙计,是那个妙计不知道 3.当打开锦囊要执行妙计时,需要的是真正的妙计,而不是我们定义的接口。 */ //Demo4想像成赵云 class Demo4 { public static void main(String[] args) { //遇到第一个问题 //MiaoJi m1=new MiaoJi_1(); //System.out.print(m1.operation()); //妙计是放在锦囊中的 JinNang jn=new JinNang(); System.out.println("刚到吴国"); jn.content(new MiaoJi_1()); System.out.println("谈判过程中"); jn.content(new MiaoJi_2()); System.out.println("离开时"); jn.content(new MiaoJi_3()); } } interface MiaoJi { //妙计执行 void operation(); } class MiaoJi_1 implements MiaoJi { public void operation(){ System.out.println("孙权要杀刘备 找乔国老帮忙。让吴国泰给孙权施加压力"); } } class MiaoJi_2 implements MiaoJi { public void operation(){ System.out.println("让吴国泰帮助,开绿灯放他们走"); } } class MiaoJi_3 implements MiaoJi { public void operation(){ System.out.println("找孙夫人断后,拦截追兵"); } } //锦囊 里面装着妙计 class JinNang{ //MiaoJI mj=new MiaoJi_3(); public void content(MiaoJi mj){//定义的是接口类型 //打开锦囊执行妙计 mj.operation(); //调用方法时执行的还是实现类中的方法 } }
多态引用在Android的接口回调。
public class MainActivity extends Activity implements OnClickListener { private Button b; private testActivity s; private EditText et; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login2); b = (Button) findViewById(R.id.buttons); et = (EditText) findViewById(R.id.editText1); b.setOnClickListener(this); s = new testActivity(); } public void onClick(View v) { switch (v.getId()) { case R.id.buttons: //接口回调,就是把接口的实例化后当作参数,传到另一个类的方法中。 //另一个类往这个接口的某个方法添加参数,然后就可以在调用的这个类中,回去参数的过程。 s.getEditText(new CallBack() { public void getResult(String result) { et.setText(result); } }); break; default: break; } } }
public class testActivity extends Fragment{ private TextView tv; public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { /*动态加载布局*/ View view = inflater.inflate(R.layout.activity_main, null); return view; } /*接口回调*/ public void getEditText(CallBack callBack){ //获取实例化的接口,然后往此方法中填入参数 callBack.getResult("hello word!"); } /*接口*/ public interface CallBack{ /* 定义一个获取信息的方法 */ public void getResult(String result); } }
面试题
import java.util.Random; public class PoliTest { public static void main(String[] args) { Parent2 p = new Child2(); p.doSomething(); } } class Parent2 { public void doSomething() { System.out.println("Parent"); } } class Child2 extends Parent2 { @Override public void doSomething() { System.out.println("Child2"); } } 以上子类重写父类的方法,则输出为子类实现的方法,如果子类中,没有此方法,则会输出父类的此方法。