4.多态,接口,内部类!

 

一,多态

1,多态

一段代码可以运行出多种形态,子类当父类来用,父类变量引用哪种子类对象就调用哪个类的方法;

2,使用多态

在定义函数的形参时,可以定义成父类类型,调用时可以传入所有子类对象;

//练习多态,

class Demo {

       public static voidmain(String[] args) {

              //创建苹果对象,并调用其方法;

              //Apple a = new Apple();

              //a.squeeze(); 

             

              Juicer j= new Juicer() ;

              j.run(new Apple());

              j.run(new Orange());

       }

}

//定义榨汁机类,简化代码;

class Juicer {

       public void run(Fruitfruit) {

              fruit.squeeze();      

       }

       //public void run(Orangeorange) {

       //     orange.squeeze();  

       //}  

}

//发现苹果和橘子类中的方法相同,只是打印主体不同,所以把这段代码提取出来,定义一个父类,

//让苹果和橘子类继承父类,这样可以简化juicer类的代码,提高代码的复用性;

abstract class Fruit {

       public abstract voidsqueeze() ;    

}

class Apple extends Fruit {

       public void squeeze() {

              System.out.println("榨了一杯苹果汁");

       }

}

class Orange extends Fruit {

       public void squeeze() {

              System.out.println("榨了一杯橘子汁");     

       }    

}

3,多态的体现

       父类的引用指向了自己的子类对象。

       父类的引用也可以接收自己的子类对象。

4,多态的前提

       必须是类与类之间有关系。要么继承,要么实现。

       通常还有一个前提:存在覆盖。

5,多态的好处

       多态的出现大大的提高程序的扩展性。

6,多态的弊端:

       虽然提高了扩展性,但是只能使用父类的引用访问父类中的成员。

在多态中成员函数的特点:

在编译时期:参阅引用型变量所属的类中是否有调用的方法,如果有,编译通过,如果没有编译失败;

在运行时期:参阅对象所属的类中是否有调用的方法;

简单总结就是:成员函数在多态调用时,编译看左边,运行看右边;

在多态中,成员变量的特点:

无论编译和运行,都参考引用型变量所属的类;

在多态中,静态成员函数的特点:

无论编译和运行,都参考引用型变量所属的类;

二,抽象类

1,抽象类

abstract修饰的类就是抽象类,其中可以定义抽象方法(abstract修饰的方法)

2,什么时候使用抽象类

当多个类拥有相同的方法签名时,我们可以将方法签名相同的方法抽取到父类中定义

子类中签名和方法体都一样的方法,直接在父类中定义,子类继承即可;

子类中签名相同,但方法体不同的方法,在父类中定义抽象方法,子类中对其重写。

3,抽象类的细节

抽象方法不能有方法体;

有抽象方法的类必须声明抽象类;

子类继承抽象类,要么重写所有抽象方法,要么也声明为抽象类;

抽象类不能创建对象;

抽象类可以没有抽象方法;

三,final关键字

1final定义的类,是最终类,不能别继承     fianl class A {}

2final定义的方法,是最终方法,不能被重写;  final  void fun(){}

3final定义的变量,是最终变量,只能赋值一次;final  int  X =4

四,模版设计模式

1,什么时候使用模版设计模式

在编程过程中,如果经常做一段重复的代码,就可以使用模版设计模式,将重复的代码定义在模版中

2,怎么使用模版设计模式

定义抽象类,其中定义一个抽象方法,用来代表每次不同的代码;

定义模版方法,将每次不同的代码写入方法中,不同的代码通过调用抽象方法来实现,模版方法防止子类修改,声明final

使用模版的时候,继承抽象类,重写抽象方法,写入每次不用的代码;

//练习:计算出运行一段代码需要的时间;

class TemplateDemo1 {

       public static voidmain(String[] args) {

              //调用方法;

              new Test().test();

       }

}

 

abstract class Template {

       //2,定义模版方法,将每次不变的方法写在模版中,不同的代码通过调用抽象对象来实现

       public final void test(){

              long start = System.currentTimeMillis();

              dosomething();

              long end = System.currentTimeMillis();

              System.out.println("使用了"+(end -start)+"毫秒");   

       }

       //1,定义一个抽象方法,用来代表每次不同的代码;

       public abstract voiddosomething();

}

//使用模版的时候,继承抽象类,重写抽象方法,写入每次不同的代码;

class Test extends Template {

       public voiddosomething() {

              for(int x=0; x<1000; x++) {

                     System.out.print(x);     

              }    

       }    

}

五,接口

1,接口

是一种特殊的抽象类,只能包含抽象方法;

2,接口和抽象类的区别

抽象类用abstract class定义,而接口用interface定义

抽象类中可以有不抽象的方法,而接口中的方法都是抽象的

抽象类用extends来继承,而接口用implements实现

抽象类中的方法没有默认修饰符,接口中的方法默认是publicabstract修饰的

抽象类中的成员变量没有默认修饰符,而接口中的成员变量是用publicstatic final修饰的

3,什么时候用抽象类,什么时候用接口

能使用接口就不用抽象类,除非必须定义带有方法体的方法;

class InterfaceDemo {

       public static voidmain(String[] args) {

              //创建person对象;

              Person p = new Person();

              p.code();

              //调用work方法;

              work1(p);

              work2(p);

                    

       }

       public static voidwork1(Coder c) {

              c.code(); 

       }

       public static voidwork2(Student s) {

              s.study();

       }

}

//创建类实现接口类方法;

class Person implements Coder, Student ,Driver {

       public void code() {

              System.out.println("编程"); 

       }    

       public void study() {

              System.out.println("学习"); 

       }

       public void drive() {

              System.out.println("开车"); 

       }

}

//创建接口类

interface Coder {

       public abstract voidcode();

}

interface Student {

       public abstract voidstudy();

}    

interface Driver {

       public abstract voiddrive();

}

六,类中的内部类

1,类中的内部类

在类中可以定义一个新的类,称为内部类;

内部类必须先创建外部类对象,才能创建内部类对象;

内部类对象持有外部类对象的一个引用“外部类名.this”,可以使用这个引用访问外部类成员;例如:A.this.name或者A.this.fun();

2,使用内部类

在定义一个类需要访问另一个类的成员时,就可以把当前类定义成另一个类的成员;

3,内部类中不能定义静态成员;

静态的本意就是不用创建对象直接使用,而内部类是需要先创建外部类对象才能使用,这是互相矛盾的;

class InnerClassDemo {

       public static voidmain(String[] args) {

              A a = new A();

              //创建内部类对象,先创建外部类

              A.B b = a.new B();

              A.B c = new A().new B();

              /*上面2段代码都是创建内部类,但是打印结果不同,

              区别在于,a.new B()的外部类对象有值,而new A().new B()外部类对象值                    null

              */

              //给变量赋值;

              a.name = "aaa";

              b.name ="bbb";

              //运行方法;

              a.fun();

              b.fun();

       }

}

class A {

       String name;

       void fun() {

              System.out.println("A.fun"+name);     

       }

       //class B就是内部类,A是外部类;B可以访问A的成员;

       class B {

              String name;

              void fun() {

                     System.out.println("B.fun"+name);     

              }    

       }

}

注意:内部类编译后产生的.class文件名字为“外部类名$内部类名.class;

七,静态内部类

1,静态内部类

在定义一个内部类的时候,可以用static修饰;

不用创建外部类对象就可以直接创建内部类对象;例如:A.B b = newA.B();

可以定义静态成员;

2,静态内部类的注意

静态内部类是外部类的一个成员,不能访问外部类的非静态成员;

当内部类在成员位置上,就可以被成员修饰符所修饰。

       比如,private:将内部类在外部类中进行封装。

              static:内部类就具备static的特性。

              当内部类被static修饰后,只能直接访问外部类中的static成员。出现了访问局限。

 

              在外部其他类中,如何直接访问static内部类的非静态成员呢?

              new 外部类名.内部类名().方法名();

 

              在外部其他类中,如何直接访问static内部类的静态成员呢?

              外部类名.内部类名.方法名();

 

       注意:当内部类中定义了静态成员,该内部类必须是static的。

                当外部类中的静态方法访问内部类时,内部类也必须是static的。

八,方法中的内部类

1,方法中的内部类

在一个方法中也能定义内部类,这个内部类只能在当前方法中使用;

2,方法中的内部类注意

方法中的内部类和类中内部类相同,都可以访问外部类成员,访问方式也相同;

方法中的内部类必须先定义再使用;

方法中的内部类不能访问到方法中定义的局部变量,除非这个局部变量被声明为final

方法中的内部类可以有多个,但是内部类的外部类只能有一个;

方法中的内部类编译后产生的.class文件名字为“外部类名$编号内部类名”.class

class MethodInnerDemo {

       public static voidmain(String[] args) {

              A a =new A();

              a.name ="aa";

              a.fun();  

       }

}

class A {

       String name;

       void fun() {

              System.out.println("A.fun name is ="+name);

              //创建方法中的内部类,并在内部类中调用外部类的成员;

              class B {

                     String name ;

                     void fun() {

                                                        System.out.println("B.fun.name="+name+"other.name="+A.this.name);

                     }    

              }

              //定义内部类

              B b = new B();

              b.name = "bb";

              b.fun();  

       }

}

九,匿名内部类

1,匿名内部类

是方法中内部类的一种,没有名字,只能使用一次;

2,定义匿名内部类

使用“new 父类名(){类定义}”的方式定义一个匿名内部类,然后使用类创建一个对象;

匿名内部类的class文件名为外部类名$编号.class

匿名内部类的写法:p.eat(newStudent() {

                                          public void study() {

                                                 System.out.println("学习"); 

                                          }    

});

       练习:   补充代码,使用匿名内部类;

class InnerTest {

       public static voidmain(String[] args) {

              Test.function().method();

/*Test.function():得出function方法时静态,所以才会被类名直接调用;

function方法后面还带有方法methodInter接口无法创建对象,说明function方法返回一个Inter的子接口,又因为function方法是静态的,所以创建成员内部类实现接口而且是用static修饰,然后重写method方法;

static class InnerClass implements Inter {

public void method() {

System.out.pritnln("成功");

}

}

*/

       }

}

interface Inter {

       public abstract voidmethod();

}

class Test{

       public static Interfunction() {

//返回匿名内部类;

              return new Inter() {

                     public voidmethod() {

                            System.out.pritnln("成功");

                     }

              };

       }

}

面试题:没有父类或者父级接口,也可以创建匿名内部类;

class Test {

            public static void main(String[] args) {

                       new Object() {

                                public static void function() {

                                        System.out.println(“因为主函数是静态的,所以匿名内部类也是静态的”);

                               }

                      }

          }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值