黑马程序员-多态,继承,内部类,抽象,接口

继承
1)提高了代码的复用性。
2)让类于类之间产生关系。有了这个关系,才有了多态的特性。

注意:千万不要为了获取其他类的功能,简化代码而继承,必须是类于类之间有所属关系才可以继承,所属关系 is a.
class Person{
String name;
int age;
}
class Student extends Person{
void study(){
System.out.println();
}
}
class Worker extends Person{
void work(){
System.out.println();
}
}
person=父 Student=子

注意:java语言中java只支持单继承,不支持多继承,因为多继承容易带来安全隐患,当多个父类中定义了相同功能,但功能内容不同时,不确定要运行哪一个。但是Java保留这种机制。并用另一种体现形式来完成表示,多实现。

java支持多层继承,也就是一个继承体系。

如何使用一个继承体系中的功能呢?
想要使用体系,先查阅体系父类的描述,因为父类中定义的是该体系中的共性功能。通过了解共性功能,就可以知道该体系的基本功能。
那么这个体系已经可以使用了。

要创建最子类的对象,为什么呢?

1)是因为有可能父类不能创建对象。2)创建子类对象可以使用更多的功能,包括特有的。

简单一句话:查阅父类功能,创建子类对象使用功能。

子父类出现后,类成员的特点:
类中成员:
1)变量
2)函数
3)构造函数

1)变量:this=子 super=父


2)子父类中的函数
当子类出现和父类一模一样的函数时,当子类对象调用该函数,会运行子类函数的内容,如同父类的函数被覆盖一样。
这种情况是函数的另一个特性:重写(覆盖)。
当子类继承父类,沿袭了父类的功能,到子类中,但是子类虽具备该功能,但是功能的内容,却和父类不一致,这时,没有必要定义新功能,而是使用覆盖特性,保留父类的功能定义,并重写功能内容。

class Tel{
void show(){}
}
class NewTel extends Tel{
void show(){
super.show();
}
}
覆盖:(1)子类覆盖父类,必须子类权限>=父类权限

           (2)静态只能覆盖静态

           (3)父类中的私有方法不能被重写。
重载:只看同名函数的参数列表。
重写:子父类方法要一模一样

3)子父类中的构造函数

在对子类对象进行初始化时,父类的构造函数也会运行,那是因为子类的构造函数默认第一行有一条隐式的语句super();
super():会访问父类中空参数的构造函数,而且子类中所有的构造函默认第一行都是super()

fu()>>>>fu(int a)
如果没有fu()的话 在子类里的构造函数里手动写fu(4)

为什么子类一定要访问父类中的构造函数?
因为父类中的数据子类可以直接获取。所以子类对象在建立时,需要先查看父类是如何对这些数据的构造函数,可以通过手动定义super语句的方式来指定。

注意:super语句一定定义在子类构造函数的第一行。

结论:子类的所有的构造函数,默认都会访问父类中空参数的构造函数。因为每一个子类构造函数内的第一行都有一句隐式的super();
      当父类中没有空参数的构造函数时,子类必须手动通过super语句形式来指定要访问的构造函数。 当然,子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。子类中至少会有一个构造函数会访问父类中的构造函数。

所有类的父类的父类是object.

final关键字  //不让覆盖
final:最终,作为一个修饰符。
1)可以修饰类,函数,变量。
2)被final修饰的类不可以被继承。为了避免被继承,被子类复写功能。
3)被final修饰的方法不可以被复写。
4)被final修饰的变量是一个常量只能复制一次,即可以修饰成员变量,有可以修饰局部变量。
   当在描述事物时,一些数据的出现只是固定的,那么这时为了增强阅读性,都给这些值起个名字,方便与阅读。而这个支部需要改变,前面加final.
   作为常量:常量的书写规范所有字母都大写,如果有多个单词间组成。单词间通过”_“连接。
static final  
5)内部类定义在类中的局部位置上是,只能访问该局部被final修饰的局部变量。

class Demo{
final int x=3;           //终身为3
x=6;                     //错误
}

 


抽象

 

抽象类的特点
1)抽象方法一定在抽象类中。
2)抽象方法和抽象类都必须被abstract关键字修饰。
3)抽象类不可以用new创建对象,因为调用抽象方法没意义。
4)抽象类中的方法要被使用,必须由子类复写其所有的抽象方法后,建立子类对象调用。
   如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。

抽象类与一般类的区别

(1)抽象类和一般类没有太大的不同。该如何描述事物,就如何描述事物,只不过,该事物出现了一些看不懂的东西,这些不确定的部分,也是该事物的功能,需要明确出来,但是无法定义主体。通过抽象方法来表示。
(2)抽象类比一般类多个抽象函数,就是在类中可以定义抽象方法。

(3)抽象类不可以实例化。

(4)抽象类虽然不能创建对象,但是也有构造函数。供子类实例化调用。

特殊:抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象。

1、被abstract修饰的函数不能同时被privatefinalstatic修饰。

     原因:

                final:被final修饰的类不能有子类。而被abstract修饰的类一定是一个父类。

                private:抽象类中的私有的抽象方法,不被子类所知,就无法被复写。

                           而抽象方法出现的就是需要被复写。

                static:如果static可以修饰抽象方法,那么连对象都省了,直接类名调用就可以了。

                            可是抽象方法运行没意义。

 

接口

接口(interface)=全抽象 implements
初期理解,可以认为是一个特殊的抽象类
当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示。
class用于定义类,interface 用于定义接口
接口定义时,格式特点
1)接口中常见定义:常量,抽象方法。
2)接口中的成员都有固定修饰符。
    常量:public static final
    方法: public abstract
记住:接口中的成员都是public的
接口:是不可以创建对象的,因为有抽象方法。
需要被子类实现,子类对接口中的抽象方法全都覆盖后,子类才可以实例化。
否则子类是一个抽象类。

接口可以被类多实现,也是对多继承不支持的转换是形式。Java支持多实现。
接口的特点
1)接口是对外暴露的规则。
2)接口是程序的功能扩展。
3)接口可以用来多实现。
4)类于接口之间是实现关系,而且类可以继承一个类的同时实现多个接口。
5)接口与接口之间可以有继承关系。

注:1、接口不可以创建对象的,因为有抽象方法。需要被子类实现(implements),子类对接口中的抽象方法全都覆盖后,子类才可以实例化。否则子类是一个抽象类。

        2、实现多个接口时,接口中不可以有返回不同类型的同名抽象函数。这样子类实现时将不能复写。


예:
interface Inter{
public static fianl int x=3;
public abstract void show();
}
class Test implements Inter{
public void show(){}                 //接口이기때문에 꼭 public사용
}

 


多态
可以理解为事物存在的多种体现形态。
动物 x=new 猫();

多态的体现:1)父类的引用指向了自己的子类对象。
                    2)父类的引用也可以接受自己的子类对象。
多态的前提:1)必须是类于类之间有关系。要么继承,要么实现
                      2)通常还有一个前提,存在覆盖
多态的好处:1)多态的出现大大的提高程序的扩展性

多态的弊端:提高了扩展性,但是只能使用父类的引用访问父类中的成员。
多态的出现代码中的特点(多态使用的注意事项):
           编译时期:参阅引用形变量所属的类中是否有调用的方法,如果有编译通过,如果没有编译失败。
           运行时期:参阅对象所属的类中是否有调用的方法。
           简单总结就是:成员函数在多态调用时,编译看左边,运行右边。
在多态中,成员变量的特点:
无论编译和运行,都参考左边(引用形变量所属的类),
多态中的父类引用调用成员变量时,如果父类和子类有同名的成员变量,那么被调用的是父类中的成员变量。  

多态中静态成员函数的特点

        无论编译和运行,都参考左边。也就是父类引用在调用静态同名函数时,被调用的是父类中的静态函数。这是因为,当类一被加载,静态函数就随类绑定在了内存中。此时,不需要创建对象,就可以使用类名直接调用。同时,父类中的静态成员函数一般是不被复写的。

 

예: abstract class animal{
abstract void eat();
}
class cat extends anmal{
void eat(){
System.out.println("吃鱼");
}
void catMouse(){
System.out.println("抓老鼠");
}
}
main(){
animal a=new cat();
animal b=new animal();
cat d=(cat)b;                        //这种是错误的
}
public static void function(animal a){
a.eat();
if(a instanceof cat){
cat c=(Cat)a;                         //强制将父类的引用,转子类类型,向下转型
c.catchMouse();
}

}

object
是所有对象的直接后者简介父类,传说中的上帝。
该类总定义的肯定是所有对象都具备的功能。

object类中已经提供了对对象是否相同的比较方法。
如果自定义类中也有比较相同的功能,没有必要重新定义。
只要沿袭父类中的功能,建立自己特有比较内容即可。这就是覆盖。

内部类
内部类的访问规则:
1)内部类可以直接访问外部类中的成员,包括私有。
   之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式=外部类名.this.XXX
2)外部类要访问内部类,必须建议内部类对象。

访问格式:
1)当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中。
可以直接建立内部类的对象。
格式:外部类名.内部类名 变量名=外部类对象.内部类.
2)当内部类在成员位置上,就可以被成员修饰符所修饰。
  比如:private:将内部类在外部类中进行封装。
        static:内部类就具备了static的特性。
        当内部类被static修饰符后,只能直接访问外部类中的static成员。出现了访问局限。
 
        在外部其他类中,如何直接访问static内部类的非静态成员呢?
        new Outer.Iner().function();
 
        在外部其他类中,如何直接访问static内部类的静态成员呢?
        Outer.Inner.function();
  注意:当内部类中定义了静态成员,该内部类必需是static的。
        当外部类中的静态方法访问内部类时,内部类也必须是static的。

        什么时候用内部类?
        当描述事物时,事物的内部还有事物,该事物用内部类来描述。因为内部事务在使用外部事物的内容。


        内部类定义在局部时
        1)不可以被成员修饰符修饰。
        2)可以直接访问外部类中的成员,因为还持有外部类中的应用。
           但是不可以访问它所在的局部中的变量,只能访问被final修饰的局部变量。

 


匿名内部类

1)匿名内部类其实就是内部类的简写格式
2)定义匿名内部类的前提:
                       内部类必须是继承一个类或者实现接口。
3)匿名内部类的格式:new 父类或者接口(){定义子类的内容}
4)其实匿名内部类就是一个匿名子类对象。而且这个对象有点胖。可以理解为带内容的对象。
5)匿名内部类中定义的方法最好不要超过3个。
              
예:

interface Inter
{
 void method();
}
class Test
{

  static Inter function(){
    return new Inter(){
 public method(){
 System.out.println("method run");
 }
 }
  }

}
class 
{
 public static void main(String[] args)
 {
  Test.function().method(); 
              show(new Inter(){
               public void method(){
              System.out.println();
   })
    }
       public static void show(Inter in){
       in.method();
}
}
分析:Test.function().method();    
Test.function():Test类中有一个静态的方法function.
.method():function这个方法运算后的结果是一个对象。而且是一个Inter类型的对象。
因为只有是Inter类型的对象,才可以调用method方法。


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值