基础知识多肽回顾:
1.多肽是方法的多肽,不是属性的多肽(多肽与属性无关)。
2.多肽的存在有三个必要条件:继承、方法重写、父类引用指向子类对象。
3.父类引用指向子类对象后,用该父类引用调用子类重写的方法,此时多肽就出现了。
原文链接
class Animal {
public void eat(){
System.out.println("父类的 吃...");
}
}
class Bird extends Animal{
@Override
public void eat(){
System.out.println("子类重写的父类的 吃吃吃...");
}
public void fly(){
System.out.println("子类新方法 飞飞飞...");
}
}
public class Sys{
public static void main(String[] args) {
Animal b=new Bird(); //向上转型
b.eat();
// b.fly(); b虽指向子类对象,但此时子类作为向上的代价丢失和父类不同的fly()方法
sleep(new Male());
sleep(new Female());//传入的参数是子类-----!!
}
public static void sleep(Human h) {//方法的参数是父类------!!!
h.sleep();
}
}
public class Human {
public void sleep() {
System.out.println("父类人类 sleep..");
}
}
class Male extends Human{
@Override
public void sleep() {
System.out.println("男人 sleep..");
}
}
class Female extends Human {
@Override
public void sleep(){
System.out.println("女人 sleep..");
}
}
输出:
子类重写的父类的 吃吃吃…
男人 sleep…
女人 sleep…
详解:
向上转型的实现
Animal b=new Bird(); //向上转型
b.eat(); // 调用的是子类的eat()方法
b.fly(); // 报错!!!!!-------b虽指向子类对象,但此
时子类作为向上转型的代价丢失和父类不同的fly()方法------
2.为何不直接Bird b=new Bird();b.eat() 呢?
这样就没有体现出面向对象的抽象的编程思想呀,降低了代码的可扩展性.
3.向上转型的好处?
sleep(new Male());//调用方法时传入的参数是子类
sleep(new Female());
public static void sleep(Human h) //方法的参数是父类
{
h.sleep();
}
如上代码就是用的向上转型,若是不用向上转型,那么有多少个子类就得在这儿写多少种不同的睡觉方法~~~~~~
说到这里是不是还是感觉云里雾里,再上个例子:
Person 可以表示为一个抽象的东西就是人。比如说人可以唱歌, 就好比Person类中有一个sing方法.
那么这个抽象的类(Person 人)可以具体到两类或者更多类 比如 男人,女人 。
Man extends Person 或者 Woman extends Person
那么男人 还有 女人 分别实现sing方法。 因为男人和女人唱歌总还是有区别的嘛。
当 Person p = new Man(); p.sing(); 这个时候就是调用男人唱歌的sing方法
当 Person p = new Woman(); p.sing(); 这个时候就是调用女人的唱歌的sing方法
这样其实就是一个java的继承,多态. 利于程序扩展. 你需要理解这种设计方式,会让你写出更易维护,简洁的代码。
class Fruit{
public void myName(){
System.out.println("我是父类 水果...");
}
}
class Apple extends Fruit{
@Override
public void myName() {
System.out.println("我是子类 苹果...");
}
public void myMore(){
System.out.println("我是你的小呀小苹果~~~~~~");
}
}
public class Sys{
public static void main(String[] args) {
Fruit a=new Apple(); //向上转型
a.myName();
Apple aa=(Apple)a; //向下转型,编译和运行皆不会出错(正确的)
aa.myName();//向下转型时调用的是子类的
aa.myMore();;
Fruit f=new Fruit();
Apple aaa=(Apple)f; //-不安全的---向下转型,编译无错但会运行会出错
aaa.myName();
aaa.myMore();
}
}
输出:
我是子类 苹果…
我是子类 苹果…
我是你的小呀小苹果~~~~~~
Exception in thread “main” java.lang.ClassCastException: com.sheepmu.Fruit cannot be cast to com.sheepmu.Apple
at com.sheepmu.Sys.main(Sys.java:30)
由此得到向下转型的意义:父类引用可以使用子类的新增方法
详解:
1.正确的向下转型
Fruit a=new Apple(); //向上转型
a.myName();
Apple aa=(Apple)a; //向下转型,编译和运行皆不会出错(正确的)
aa.myName();
aa.myMore();
a指向子类的对象,所以子类的实例aa也可以指向a啊~~
向下转型后因为都是指向子类对象,所以调用的当然全是子类的方法~~
2.不安全的向下转型
Fruit f=new Fruit();
Apple aaa=(Apple)f; //-不安全的---向下转型,编译无错但会运行会出错
aaa.myName();
aaa.myMore();
f是父类对象,子类的实例aaa肯定不能指向父类f啊~~~
3.Java为了解决不安全的向下转型问题,引入泛型的概念
4.为了安全的类型转换,最好先用 if(A instanceof B) 判断一下下
这里引出一个问题:JAVA的面向对象应该怎样理解。(之前就突然被一个面试问到对面向对象、面向过程的理解)有很多种答案,这里是B站上看到的一个老师讲的。
所有的程序其实只有三个核心元件:变量、选择语句、循环语句。
面向过程变成:我们可以通过方法,来把这三个东西放在一起。然后通过方法一方法二串联起来,最终形成一个程序。
面向对象:对象,它是一个更高级的组织方式。我们可以把方法、变量放到对象里面。更高级的组织形式可以做更复杂的程序。