面向对象4
1、多态
thinking in java3中的多态
People are often confused by other, non-object-oriented features of Java, like method overloading, which are sometimes presented as object-oriented. Don't be fooled: If it isn't late binding, it isn't polymorphism
按文面翻译
人们总是被java的另一种非面向对象的特性所困惑,就像方法重载,有时候它以面向对象而存在,请不要犯傻,如果没有后期绑定(也就是运行期的动态绑定),它就不是多态.
所以,这段话要表达的意思就是说,多态要有动态绑定,否则就不是多态,方法重载也不是多态(因为方法重载是编译期决定好的,没有后期也就是运行期的动态绑定)
多态存在的三个必要条件
- 继承
- 重写
- 父类引用指向子类对象
比如:
Parent p = new Child();
多态的实现方式
方式一:重写:
方式二:接口
-
1. 生活中的接口最具代表性的就是插座,例如一个三接头的插头都能接在三孔插座中,因为这个是每个国家都有各自规定的接口规则,有可能到国外就不行,那是因为国外自己定义的接口类型。
-
2. java中的接口类似于生活中的接口,就是一些方法特征的集合,但没有方法的实现。具体可以看 java接口 这一章节的内容。
方式三:抽象类和抽象方法
多态的好处:提高代码的重用性,降低模块之间的耦合度
package LESSON6; class Animal1{ String name; } class Food1{ String name; } class Feeder1{ String name; public void feed(Animal1 animal,Food1 food){ System.out.println(name+"给"+animal.name+"喂"+food.name); } } class Rabbit1 extends Animal1{} class Dog1 extends Animal1{} class Bone1 extends Food1{} class Carrot1 extends Food1{} public class DEMO8 { /** * @param args */ public static void main(String[] args) { //多态的好处:提高代码的重用性,降低模块之间的耦合度 Feeder1 feeder=new Feeder1(); feeder.name="jack"; Animal1 rabbit=new Rabbit1(); rabbit.name="小白兔"; Animal1 dog=new Dog1(); dog.name="牧羊犬"; Food1 bone=new Bone1(); bone.name="大骨头"; Food1 carrot=new Carrot1(); carrot.name="胡萝卜"; feeder.feed(rabbit, carrot); feeder.feed(dog, bone); } }
package LESSON6; class Animal{ public String name; public void eat(){ System.out.println("动物具有吃的能力"); } } class Food{ public String type; } class Feeder{ public void feed(String name,String type){ System.out.println("喂"+name+"吃"+type); } } class Dog extends Animal{ //重写 public void eat(){ System.out.println("我喜欢吃骨头"); } //子类独有方法 public void watchdoor(){ System.out.println("看门"); } } class Rabbit extends Animal{ public void eat(){ System.out.println("我喜欢吃胡萝卜"); } } public class DEMO6 { // 多态:指对象的多种形态
// 多态的前提:继承关系中
// 多态的表现:向上转型和向下转型
public static void main(String[] args) { //1 引用多态 Animal animal=new Animal();//父类的引用指向本类对象 Animal dog=new Dog();//父类引用指向子类对象(向上转型:子类对象->>父类对象) dog.name="狗";//通过父类的引用变量调用父类属性
Dog dog1=(Dog)dog;//向下转型:父类对象->>子类对象(前提是先进行向上转型)
Dog dog2=(Dog)Animal;//java.lang.ClassCastException类型转化异常(未进行向上转型)
//2 方法多态 animal.eat();//创建本类对象时,调用的方法为本类方法。 //输出 动物具有吃的能力 dog.eat();//创建子类对象时,调用的方法为子类重写的方法或者继承的方法。 //输出 我喜欢吃骨头 //dog.watchdoor() //不能通过父类的引用调用子类独有的方法 Food food=new Food(); food.type="骨头"; Feeder Feed=new Feeder(); Feed.feed(dog.name,food.type); } }
2、抽象类,抽象方法
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。
父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。
在Java中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。
package LESSON7; //抽象类:[修饰符] abstract class 类名 abstract class Shape{ //抽象方法:[修饰符] abstract 返回值类型 方法名 ([参数列表]); public abstract void area(); //如果一个类中声明了抽象方法,该类必须是抽象类 //抽象类中可以声明普通方法和抽象方法 public void test(){ System.out.println("test"); } } class Circle extends Shape{ public double r; public final double PI=3.14; public Circle(double r) { this.r=r; } @Override public void area() { System.out.println("该圆的面积是"+PI*r*r); } } public class demo { public static void main(String[] args) { Shape c=new Circle(2); c.area(); } }
3、接口
接口多实现
package LESSON7; interface A{ public abstract void a(); } interface B{ public abstract void b(); } interface C{ public abstract void c(); } //接口可以多实现,类只能单继承但可以多重继承 class D implements A,B,C{ @Override public void a() { System.out.println("a"); } @Override public void b() { System.out.println("b"); } public void c() { System.out.println("c"); } } public class demo2 { public static void main(String[] args) { D d=new D(); d.a(); d.b(); d.c(); A d2=new D(); d2.a();//只能调用a方法 } }
接口多继承