java 接口、继承、多态
1.继承
继承的基本思想是基于某个父类的扩展,制定出一个新的子类,子类可以继承父类原有的属性和方法,也可以增加原来父类所不具备的属性和方法,
或者直接重写父类中的某些方法,这样做不仅可以减少开发周期,也可以提高代码的可维护性和可扩展性。
public class Test { public Test(){ } protected void doSomething() { } protected Test doIt() { return new Test(); } } //extends关键字用来表示继承关系 is-a class Test02 extends Test{ public Test02(){ /** * 如果子类没有显示的调用父类的构造器,则自动调用父类的无参构造器 * 但是当父类没有无参构造器且存在有参构造器时,子类需要显示的使用super关键字调用父类的有参构造器 * 且必须在构造器的第一句使用super关键字 */ super(); //super关键字:调用父类的构造方法 super.doSomething();//super关键字: 调用父类的成员方法 } //新增的方法 public void doSomethingNew(){ } //当子类的方法名及参数与父类中的某方法一样时,此时称为重写(重写方法里的实现) //重写能够改变方法的修饰权限,但是修饰权限只能大于或者等于父类的修饰权限,如下面protec->public public void doSomething() { } //重写也可以改变方法的返回值类型(1.5之后),但是重写方法的返回值类型必须是父类的返回值类型或者父类的返回值的子类 //如下:Test02 是Test的子类 public Test02 doIt() { return new Test02(); } }
2.子类的初始化对象
在继承的机制中,创建一个子类的对象,将包含一个父类子对象,这个对象与父类创建的对象是一样的,两者的区别在于后者来自外部,而前者来自子对象的内部,也就是说当子类实例化时,父类对象也相应的被实例化。
public class Parent { public Parent() { System.out.println("调用父类的Parent()构造方法"); } public static void main(String[] args) { Subroutine subroutine = new Subroutine(); } } class SubParent extends Parent{ public SubParent(){ System.out.println("调用子类的SubParent()构造方法"); } } class Subroutine extends SubParent{ public Subroutine(){ System.out.println("调用子类的Subroutine()构造方法"); } }
输出结果:先输出的是父类的构造器方法里的内容。
调用父类的Parent()构造方法
调用子类的SubParent()构造方法
调用子类的Subroutine()构造方法
3.方法的重载
方法的重载指的是在同一个类中允许存在一个以上的相同名字的方法,但是方法的参数个数或者类型不同。
public class OverloadTest { public static int add(int a ,int b ){ return a + b; } public static double add (double a, double b){ return a + b; } public static int add(int a ){ return a; } public static int add (int a , double b){ return a; } public static int add(double a, int b){ return b; } public static int add (int... a){ int sum = 0; for(int value : a){ sum += value; } return sum; } public static void main(String[] args) { System.out.println("调用 add(int a ,int b )方法: "+add(1,2)); System.out.println("调用add (double a, double b)方法: "+add(0.5, 0.2)); System.out.println("调用不定长参数add (int... a) 方法: "+add(1,2,3,4)); } }
4.多态
一个变量能够引用多种类型的现象称为多态,在运行的时候能够自动的选择调用哪个方法称为动态绑定。
public class Person { public void walk(){ System.out.println("人每天走4000步!"); } public static void main(String[] args) { Person [] persons = new Person[2]; persons[0] = new Child(); persons[1] = new Oldman(); for(Person p : persons){ p.walk(); } } } class Child extends Person{ //重写 public void walk() { System.out.println("小孩每天走-1步!"); } } class Oldman extends Person{ //重写 public void walk() { System.out.println("老头每天走10000步!"); } }
结果:
小孩每天走-1步!
老头每天走10000步!
5.抽象类和接口
抽象类用abstract关键字表示,有抽象方法的类必须是抽象类,继承抽象类的子类必须实现抽象方法。语法:
public abstract class AbstractTest { public abstract void test(); public void walk(){ System.out.println("有实现体的方法"); } }
层次越高的类越抽象,比如上面4多态中的Person类,在你不知道哪一类人的时候可能无法去定义Walk()方法里的内容,因此可以用抽象类去表示,
抽象方法不需要实现体。
但是由于java的继承是单继承,但是某些子类并不需要去实现父类的抽象方法(但是继承抽象类的所有子类都必须实现抽象方法~~),因此
接口的概念就出现了,把并不是所有子类都要实现的方法放到接口中,让子类去选择是否实现接口去重写方法。
接口:
接口是抽象类的延伸,可以看做是纯粹的抽象类,接口中的方法都没有方法体,默认为public,而成员变量默认为常量,static final。
语法如下:
public interface InteTest { //方法默认为public void test(); int add(); } //implements实现接口 class test implements InteTest{ public void test() { } public int add() { return 0; } }
6.内部类
在一个类中定义了一个其他类,则这个类里面的新定义的类就叫做内部类。
*对于内部类变量与外部类重名,且内部类需要调用外部类的变量可以使用 外部类名.this.变量名 进行调用
public class OuterClass { class InnerClass{ //定义内部类 int y =0; //内部类的成员变量 public InnerClass(){ //内部类构造方法 } public void inf(){ //内部类方法 } } InnerClass inner = new InnerClass(); //在外部类实例化内部类对象 public InnerClass doit(){ //外部类的方法 //y=4; //外部类无法直接使用内部类的成员变量,内部类可以调用外部类的成员变量和方法 inner.y = 4; return new InnerClass(); } public static void main(String[] args) { OuterClass out = new OuterClass(); //错误 内部类的对象实例化操作必须在外部类或者外部类的非静态方法中实现 //InnerClass innerClass = new InnerClass(); OuterClass.InnerClass in1 = out.doit(); OuterClass.InnerClass in2 = out.new InnerClass();//依赖外部类对象 } }
使用内部类实现接口,内部类为private修饰,这样可以隐藏内部类的实现。
public class InterfaceInter { public static void main(String[] args) { OutClassTest out = new OutClassTest(); Outinterface inte = out.some(); inte.doSomething(); } } //定义一个接口 interface Outinterface{ void doSomething(); } class OutClassTest{ //可以定义多个内部类去实现接口的doSomething方法,而正常的类是没办法以多个方法去实现接口的方法的 private class InnerClass implements Outinterface{ //非内部类不能使用private和protected修饰符 InnerClass(String s) { System.out.println(s); } public void doSomething() { System.out.println("内部类的doSomething方法"); } } //定义方法返回接口 public Outinterface some(){ return new InnerClass("内部类的构造方法"); } }
匿名内部类:
public class InnerClassTest { public static void main(String[] args) { intef i = new intef(){ public void doIt(){ System.out.println("匿名内部类方法"); } }; //语法:new xx(){}; 创建一个实现intef接口的匿名类的对象 i.doIt(); } } interface intef{ void doIt(); }