【抽象类的特点】 
1,抽象类和抽象方法都需要被abstract修饰。 
抽象方法一定要定义在抽象类中。 
2,抽象类不可以创建实例,原因:调用抽象方法没有意义。 
3,只有覆盖了抽象类中所有的抽象方法后,其子类才可以实例化。 
否则该子类还是一个抽象类。 
 
 
之所以继承,更多的是在思想,是面对共性类型操作会更简单。 
 
 
【细节问题】 
1,抽象类一定是个父类?         
        是的,因为不断抽取而来的。 
 
2,抽象类是否有构造函数? 
        有,虽然不能给自己的对象初始化,但是可以给自己的子类对象初始化。 
        抽象类和一般类的异同点: 
        相同: 
                1,它们都是用来描述事物的。 
                2,它们之中都可以定义属性和行为。 
 
        不同: 
                1,一般类可以具体的描述事物。 
                        抽象类描述事物的信息不具体 
                2,抽象类中可以多定义一个成员:抽象函数。 
                3,一般类可以创建对象,而抽象类不能创建对象。 
 
3,抽象类中是否可以不定义抽象方法。 
        是可以的,那这个抽象类的存在到底有什么意义呢?仅仅是不让该类创建对象。 
 
 
4,抽象关键字abstract不可以和哪些关键字共存?         
        1,final: 
        2,private: 
        3,static: 
 
【final关键字】 
是一个修饰符,可以修饰类,方法,变量(成员变量,局部变量,静态变量)。 
【特点】 
1,final修饰的类是一个最终类,不能在派生子类。 
如果类中从出现部分可以重写,部分不可以?怎么办?只要让指定的方法最终化就可以了。 
2,final修饰的方法是最终方法,不可以给重写。 
3,final修饰的变量是一个常量,只能被赋值一次。 
【什么时候会在程序中定义final常量呢?】 
当程序中一个数据使用时是固定不变的,这时为了增加阅读性,可以该该数据起个名字。 
这就是变量,为了保证这个变量的值不被修改,加上final修饰,这就一个阅读性很强的常量。 
书写规范,被final修饰的常量名所有的字母都是大写的。如果由多个单词组成单词间通过 _ 连接。 
 
接口中的成员已经被限定为固定的几种。 
【接口的定义格式先介绍两种:】 
1,定义变量,但是变量必须有固定的修饰符修饰,public static final 所以接口中的变量也称之为常量。 
2,定义方法,方法也有固定的修饰符,public abstract 
接口中的成员都是公共的。 
 
【接口的特点】 
1,接口不可以创建对象。 
2,子类必须覆盖掉接口中所有的抽象方法后,子类才可以实例化。 
        否则子类是一个抽象类。 
定义子类去覆盖接口中的方法。子类必须和接口产生关系,类与类的关系是继承,类与接口之间的关系是 实现。通过 关键字 implements 
 
【接口最重要的体现】 
解决多继承的弊端。将多继承这种机制在java中通过多实现完成了。 
 
【怎么解决多继承的弊端呢?】 
弊端:多继承时,当多个父类中有相同功能时,子类调用会产生不确定性。 
其实核心原因就是在于多继承父类中功能有主体,而导致调用运行时,不确定运行哪个主体内容。 
为什么多实现就解决了呢? 
因为接口中的功能都没有方法体,由子类来明确。 
 
【基于接口的扩展。】 
子类通过继承父类扩展功能,通过继承扩展的功能都是子类应该具备的基础功能。 
如果子类想要继续扩展其他类中的功能呢?这时通过实现接口来完成。 
 
接口的出现避免了单继承的局限性。 
父类中定义的事物的基本功能。 
接口中定义的事物的扩展功能。 
 
【接口出现后的一些小细节】 
1,类与类之间是继承(is a)关系,类与接口之间是实现(like a)关系, 
        接口与接口之间是继承关系,而且可以多继承。 
 
多态: 
        【体现】 
                父类的引用或者接口的引用指向了自己的子类对象。 
                Dog d = new Dog();//Dog对象的类型是Dog类型。 
                Animal a = new Dog();//Dog对象的类型右边是Dog类型,左边Animal类型。 
        【好处】 
                提高了程序的扩展性。 
        【弊端】 
                通过父类引用操作子类对象时,只能使用父类中已有的方法,不能操作子类特有的方法。 
        【前提】 
                1,必须有关系:继承,实现。 
                2,通常都有重写操作。 
        【子类的特有方法如何调用呢?】 
        Animal a = new Dog();//Animal是父类型,new Dog()是子对象。 
        但是父类型引用指向子类对象时,这就是让子类对象进行了类型的提升(向上转型)。 
        向上转型好处:提高了扩展性,隐藏了子类型。弊端:不能使用子类型的特有方法。 
        如果要想使用子类的特有方法,只有子类型可以用。 
        可以向下转型,强制转换。 
        Animal a = new Dog(); 
        a.eat(); 
        Dog d = (Dog)a;//将a转型为Dog类型。向下转型。 
        d.lookHome(); 
        向下转型什么时候用?当需要使用子类型的特有内容时。 
         
        注意:无论向上还是向下转型,最终都是子类对象做着类型的变化。 
         
        【向下转型的注意事项】 
        Animal a = new Dog(); 
        //Cat c = (Cat)a;向下转型因为不明确具体子类对象类型,所以容易引发ClassCastException异常。 
        所以为了避免这个问题,需要在向下转型前,做类型的判断。 
        判断类型用的是关键字 instanceof 
        if(a instanceof Cat)//a指向的对象的类型是Cat类型。 
        { 
                //将a转型Cat类型。 
                Cat c = (Cat)a; 
                c.catchMouse(); 
        } 
        else if(a instanceof Dog) 
        { 
                Dog d = (Dog)a; 
                d.lookHome(); 
        } 
 
        【转型总结】 
        1,什么时候使用向上转型呢? 
                提高程序的扩展性,不关系子类型(子类型被隐藏)。 
                需要用子类的特有方法吗?不需要,哦了。向上转型。 
        2,什么时候使用向下转型呢? 
                需要使用子类型的特有方法时。 
                但是一定要使用 instanceof 进行类型的判断。避免发生 ClassCastException 
多态中,成员调用的特点。 
 
1,成员变量。 
        当子父类中出现同名的成员变量时。 
                多态调用该变量时: 
                        编译时期:参考的是引用型变量所属的类中是否有被调用的成员变量。没有,编译失败。 
                        运行时期:也是调用引用型变量所属的类中的成员变量。 
                简单记:编译和运行都参考等号的左边。 
                                编译运行看左边。 
 
2,成员函数。 
        编译,参考左边,如果没有,编译失败。 
        运行,参考右边的对象所属的类。 
                编译看左边,运行看右边。 
         
        对于成员函数是动态绑定到对象上。 
 
3,静态函数。 
        编译和运行都参考左边。 
 
        静态函数是静态的绑定到类上。 
 
 
【结论】 
对于成员变量和静态函数,编译和运行都看左边。 
对于成员函数,编译看左边,运行看右边。 
 |   
        
 
    
    
    
     
 
 |