zoukankan      html  css  js  c++  java
  • 继承与多态——动手动脑

    一、继承条件下的构造方法调用

    package example;
    
    class Grandparent 
    {
    
    
        public Grandparent()
         {
    
                System.out.println("GrandParent Created.");
        
    }
    
    
        public Grandparent(String string) 
        {
    
                System.out.println("GrandParent Created.String:" + string);
        
     }
    
    }
    
    
    
    class Parent extends Grandparent
    {
    
    
        public Parent()
         {
    
                //super("Hello.Grandparent.");
    
                System.out.println("Parent Created");
        
           // super("Hello.Grandparent.");
    
          }
    
    }
    
    
    
    class Child extends Parent 
    {
    
    
        public Child()
         {
        
            System.out.println("Child Created");
    
          }
    
    }
    
    
    
    public class TestInherits 
    {
    
    
        public static void main(String args[])
         {
    
                Child c = new Child();
        
      }
    
    }

    结论:通过 super 调用基类构造方法,必须是子类构造方法中的第一个语句。

    二、

    package example;
    
    public class ExplorationJDKSource {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            System.out.println(new A());
        }
    
    }
    
    class A{}

    前面示例中,main方法实际上调用的是: public void println(Object x),这一方法内部调用了String类的valueOf方法。 valueOf方法内部又调用Object.toString方法: public String toString() { return getClass().getName() +"@" + Integer.toHexString(hashCode()); } hashCode方法是本地方法,由JVM设计者实现: public native int hashCode();

    三、神奇的“+”号

    package example;
    
    public class Fruit
    {
            
        public String toString()
        {
            return "Fruit toString.";
        }
    
        public static void main(String args[])
        {
            Fruit f=new Fruit();
            System.out.println("f="+f);
        //    System.out.println("f="+f.toString());
        }
    }

    结论: 在“+”运算中,当任何一个对象与一个String对象,连接时,会隐式地调用其toString()方法,默认情况下,此方法返回“类名 @ + hashCode”。为了返回有意义的信息,子类可以重写toString()方法。

    四、在子类中,若要调用父类中被覆盖的方法,可以使用super关键字。

    public class We {
    
     
    
    public static void main(String[] args) {
    
    // TODO Auto-generated method stub
    
    Son s=new Son();
    
    s.Cs();
    
    }
    
    }
    
    class Parent{ 
    
    void Cs(){
    
    System.out.println("父类方法");
    
    }
    
    }
    
    class Son extends Parent{
    
    void Cs(){
    
    super.Cs();
    
    System.out.println("子类方法");
    
    }
    
    }

    Java“方法覆盖”的语法规则:

    (1)覆盖方法的允许访问范围不能小于原方法。

    (2)覆盖方法所抛出的异常不能比原方法更多。

    (3)声明为final方法不允许覆盖。 例如,Object的getClass()方法不能覆盖。

    (4)不能覆盖静态方法。

    五、

    package example;
    
    public class ParentChildTest {
        public static void main(String[] args) {
            Parent parent=new Parent();
            parent.printValue();
            Child child=new Child();
            child.printValue();
            
            parent=child;
            parent.printValue();
            
            parent.myValue++;
            parent.printValue();
            
            ((Child)parent).myValue++;
            parent.printValue();
            
        }
    }
    
    class Parent{
        public int myValue=100;
        public void printValue() {
            System.out.println("Parent.printValue(),myValue="+myValue);
        }
    }
    class Child extends Parent{
        public int myValue=200;
        public void printValue() {
            System.out.println("Child.printValue(),myValue="+myValue);
        }
    }

    当子类与父类拥有一样的方法,并且让一个父类变量引用一个子类对象时,到底调用哪个方法,由对象自己的“真实”类型所决定,这就是说:对象是子类型的,它就调用子类型的方法,是父类型的,它就调用父类型的方法。

    这个特性实际上就是面向对象“多态”特性的具体表现。

    如果子类与父类有相同的字段,则子类中的字段会代替或隐藏父类的字段,子类方法中访问的是子类中的字段(而不是父类中的字段)。如果子类方法确实想访问父类中被隐藏的同名字段,可以用super关键字来访问它。

    如果子类被当作父类使用,则通过子类访问的字段是父类的!

    牢记:在实际开发中,要避免在子类中定义与父类同名 的字段。不要自找麻烦!——但考试除外,考试中出这种题还是可以的。

    六、动物园

    package zoo1;
    
    public class Zoo 
    {
    
        public static void main(String args[])
        {
    
            Feeder f = new Feeder("小李");
    
            // 饲养员小李喂养一只狮子
    
            f.feedLion(new Lion());
    
            // 饲养员小李喂养十只猴子
    
            for (int i = 0; i < 10; i++)
             {
    
                f.feedMonkey(new Monkey());
    
            }
            
            // 饲养员小李喂养5只鸽子
    
            for (int i = 0; i < 5; i++)
             {
    
                f.feedPigeon(new Pigeon());
    
            }
        
        }
    
    }

    简化Feeder类:Feeder类的三个喂养方法现在可以合并为一个feedAnimal()方法,注意它接收一个类型为Animal参数,而不是三个具体的动物类型。 依据多态特性,此方法将可以接收任何一个派生自Animal类的子类对象

    package zoo2;
    
    public class Zoo 
    {
    
        
        public static void main(String args[])
        {
    
                Feeder f = new Feeder("小李");
    
                //饲养员小李喂养一只狮子
    
                f.feedAnimal(new Lion());
                //饲养员小李喂养十只猴子
    
                for (int i = 0; i < 10; i++) 
            {
    
                    f.feedAnimal(new Monkey());
        
            }
    
                //饲养员小李喂养5只鸽子
    
                for (int i = 0; i < 5; i++) 
            {
    
                    f.feedAnimal(new Pigeon());
    
                }
    
        }
    
    }

    修改feedAnimals方法,让它接收一个Animal数组。

    现在只需要一句代码,就 可以模拟出喂养一批各种 各样的动物的过程。

    package zoo3;
    
    public class Zoo {
    
        public static void main(String args[]) {
            Feeder f = new Feeder("小李");
            Animal[] ans = new Animal[16];
    
            //饲养员小李喂养一只狮子
            ans[0] = new Lion();
            //饲养员小李喂养十只猴子
            for (int i = 0; i < 10; i++) {
                ans[1 + i] = new Monkey();
            }
            //饲养员小李喂养5只鸽子
            for (int i = 0; i < 5; i++) {
                ans[11 + i] = new Pigeon();
            }
    
            f.feedAnimals(ans);
        }
    }
    
    class Feeder {
    
        public String name;
    
        Feeder(String name) {
            this.name = name;
        }
    
        public void feedAnimals(Animal[] ans) {
            for (Animal an : ans) {
                an.eat();
            }
        }
    }
    
    abstract class Animal {
    
        public abstract void eat();
    }
    
    class Lion extends Animal {
    
        public void eat() {
            System.out.println("我不吃肉谁敢吃肉!");
        }
    }
    
    class Monkey extends Animal {
    
        public void eat() {
            System.out.println("我什么都吃,尤其喜欢香蕉。");
        }
    }
    
    class Pigeon extends Animal {
    
        public void eat() {
            System.out.println("我要减肥,所以每天只吃一点大米。");
        }
    }

    Feeder类的feedAnimals()方法接收的是一个Animal数组,这有一个限制,就是只能创建固定个数的数组,无法动态地增减动物个数。

    修改feedAnimals方法,让其接收一个元素数目可变的对象容器。

    package zoo4;
    
    import java.util.Vector;
    
    public class Zoo {
    
        public static void main(String args[]) {
            Feeder f = new Feeder("小李");
            Vector<Animal> ans = new Vector<Animal>();
    
            //饲养员小李喂养一只狮子
            ans.add(new Lion());
            //饲养员小李喂养十只猴子
            for (int i = 0; i < 10; i++) {
                ans.add(new Monkey());
            }
            //饲养员小李喂养5只鸽子
            for (int i = 0; i < 5; i++) {
                ans.add(new Pigeon());
            }
            f.feedAnimals(ans);
        }
    }
    
    class Feeder {
    
        public String name;
    
        Feeder(String name) {
            this.name = name;
        }
    
        public void feedAnimals(Vector<Animal> ans) {
            for (Animal an : ans) {
                an.eat();
            }
        }
    }
    
    abstract class Animal {
    
        public abstract void eat();
    }
    
    class Lion extends Animal {
    
        public void eat() {
            System.out.println("我不吃肉谁敢吃肉!");
        }
    }
    
    class Monkey extends Animal {
    
        public void eat() {
            System.out.println("我什么都吃,尤其喜欢香蕉。");
        }
    }
    
    class Pigeon extends Animal {
    
        public void eat() {
            System.out.println("我要减肥,所以每天只吃一点大米。");
        }
    }

    从这个示例中可以看到,通过在编程中应用多态,可以使我们的代码具有更强的适用性。当需求变化时,多态特性可以帮助我们将需要改动的地方减少到最低限度。

    多态编程有两种主要形式: (1)继承多态:示例程序使用的方法 (2)接口多态:使用接口代替抽象基类,这个任务留为作业。

  • 相关阅读:
    Python GUI编程实例
    Python MySQL事务、引擎、索引及第三方库sqlalchemy
    Python 魔法方法简介
    Python sax模块(SAX解析XML)
    Python minidom模块(DOM写入和解析XML)
    【LOJ】#2432. 「POI2014」代理商 Couriers
    【51nod】1559 车和矩形
    【LOJ】#2430. 「POI2014」沙拉餐厅 Salad Bar
    【LOJ】#2105. 「TJOI2015」概率论
    【BZOJ】1336: [Balkan2002]Alien最小圆覆盖
  • 原文地址:https://www.cnblogs.com/zql-42/p/11720794.html
Copyright © 2011-2022 走看看