java之继承和多态

94 阅读7分钟

继承和多态

继承和多态是面向对象非常重要的一个环节,继承能够复用一些定义好的类,减少代码冗余量,多态可以动态调整对现象的调用,降低对象之间的关系

类的封装

封装就是将类的某些信息隐藏在类内部,不允许外部程序直接访问,只能通过该类提供的方法来实现对隐藏信息的操作和访问。

封装的步骤一般是,对属性设置private 。为每一个属性创建get和set方法,用于属性的读写,在赋值和取值方法中加入对属性值的合法判断
//封装简易类demo
import java.util.Scanner;

public class packagingClass {
    public static void main(String [] args){
        Empolye em_1=new Empolye();
        System.out.println("请输入员工信息");
        Scanner input=new Scanner(System.in);
        System.out.print("姓名:");
        em_1.setName(input.next());
        System.out.print("年龄:");
        em_1.setAge(input.nextInt());
        System.out.print("手机号");
        em_1.setPhone(input.next());
        System.out.print("地址");
        em_1.setAddress(input.next());
        System.out.println("姓名"+em_1.getName());
        System.out.println("年龄"+em_1. getAge());
        System.out.println("手机号"+em_1.getPhone());
        System.out.println("地址"+em_1.getAddress());

    }
}
class Empolye{
    private String name;
    private int age;
    private String address;
    private String phone;
    public String getName(){
         return name;
    }
    public int getAge(){
        return age;
    }
    public String getAddress(){
        return address;
    }
    public String getPhone(){
        return phone;
    }
    public void setName(String name){
        this.name=name;
    }
    public void setAge(int age){
        if(age>18 && age<40){
             this.age=age;
        }else{
            System.out.println("年龄必须在20-40之间");
        }
    }
    public void setPhone(String phone){
        if(phone.length() == 11){
            this.phone=phone;
        }else{
            System.out.println("手机号码不合法");
        }
    }
    public void setAddress(String address){
        this.address=address;
    }
}

//图书信息类
public class BookTest {
    public static void main(String [] args){
        BookInfo books_1=new BookInfo();
        books_1.setBookName("《小木偶》");
        books_1.setBookNum(201);
        books_1.detail();
        BookInfo books_2=new BookInfo();
        books_2.setBookNum(190);
        books_2.setBookName("《堂吉诃德》");
        books_2.detail();
    }
}
class  BookInfo{
    private String bookName;
    private int bookNum;
    public String getBookName(){
        return this.bookName;
    }
    public String getBookNum(){
        return this.bookName;
    }
    public void setBookName(String name){
        this.bookName=name;
    }
    public void setBookNum(int num){
        if(num >200){
            System.out.println(this.bookName+"书本不能超过两百页面");
            this.bookNum=200;
        }else{
            this.bookNum=num;
        }

    }
    public void detail(){
        System.out.println(this.bookName+"这本书共有"+this.bookNum+"页");
    }
}

继承

继承通过extends关键字进行继承。 如果在父类中存在有参的构造方法并没有重载无参的构造方法,那么在子类中必须要有有参的构造方法,因为如果在子类中不含有构造方法,默认调用父类无参的构造方法,而在父类中没有无参的构造方法,会出错

super关键字

因为子类不能继承父类的构造方法,因此,如果要调用父类的构造方法,可以使用super关键字,super可以访问父类的构造方法,普通方法和属性

public class supers {
    public static void main(String [] args){
        Liu l=new Liu();
        l.display();
    }
}
class People{
   public  int age=18;
   public void message(){
       System.out.println("this is Father");
   }
}
class Liu extends People{
    public void message(){
        System.out.println("this is Child");
    }
    public int age=12;
    public void display(){
        message();
        super.message();
         System.out.println("父类里的年龄是"+super.age);
         //通过super调用父类的属性和方法
    }
}

this和super的区别

this指向的是当前对象,super指向的是父类对象 this()调用的是当前对象的构造方法,super调用的是父类的构造方法

对象类型转换

对象类型转换指的是创建对象时候 ,类型是父类,new的对象却是子类,或者类型是子类,这样去new(sonClass) fatherClass;

public class Anmial{
 public static void main(String [] args){
    Anmials anmials=new Dog(); //向上转型,把dog类转换为Anmials类
     Dog dog=(Dog) anmials;//向下转型,把animals类转换未Dog类
     System.out.println(anmials.name);
     System.out.println(anmials.StaticName);
     anmials.eat();
     anmials.staticEat();
     dog.eat();
     dog.staticEat();
 }
}
class Anmials{
    public String name="Anmials:动物";
    public String StaticName="Anmail:可爱的动物";
    public void eat(){
        System.out.println("吃饭");
    }
    public void staticEat(){
        System.out.println("动物在吃饭");
    }
}
class Dog extends Anmials{
  public String name="dog:狗";
  public String str="喵星人";
  public String StaticName="不,我是汪星人";
  public void eat(){
      System.out.println("吃饭");
  }
  public void staticEat(){
      System.out.println("狗子在吃饭");
  }
  public  void eatMethod(){
      System.out.println("狗喜欢吃*");
  }
}

方法重载

java允许同一个类中定义多个同名方法,只要它们的形参列表不同即可,如果同一个类中包含了两个或者两个以上方法名相同的方法,但是参数列表不同这种情况称为方法重载

方法重写

在子类中,如果有跟父类相同名称,相同返回类型,相同参数列表的方法,称为方法的重写

多态

多态是面向对象语言的一个重要特征,它是指在父类中定义的属性和方法被子类继承之后,可以具有不同的数据类型或表现出不同的含义。如果要实现多态,必须要满足,继承,重写,向上转型才能实现

public class Anmial{
 public static void main(String [] args){
   Figure figure;
   figure=new Rectangle(9.1,9.2);
   System.out.println(figure.area());
   figure=new Tirangle(9.1,9.2);
   System.out.println(figure.area());
   figure=new Figure(1.1,1.2);
   System.out.println(figure.area());
 }
}

class Figure{
    public double dim1;
    public  double dim2;
    public  Figure(double dim1,double dim2){
    this.dim1=dim1;
    this.dim2=dim2;
    }
    public double area(){
        System.out.println("父类里的方法,没有实际意义");
         return 0;
    }
}
class Rectangle extends Figure{
    public Rectangle(double dim1, double dim2) {
        super(dim1, dim2);
    }
    public double area(){
        System.out.println("长方形的面积");
        return this.dim1 * this.dim2;
    }
}

class Tirangle extends Figure{
    public Tirangle(double dim1,double dim2){
        super(dim1,dim2);
    }
    public double area(){
        System.out.println("三角形的面积");
        return this.dim1 * this.dim2 /2;
    }
}

instanceof

instanceof 用于判断对象是否是一个类,或者接口,抽象类。

public class Anmial{
 public static void main(String [] args){
   Figure figure=new Figure(1.1,9.2);
     Rectangle rectangle=new Rectangle(1.2,9.2);
     Tirangle tirangle=new Tirangle(1.6,9.2);
     System.out.println(figure instanceof  Figure);
     System.out.println(rectangle instanceof Figure);
     System.out.println(tirangle instanceof Figure);
 }
}

class Figure{
    public double dim1;
    public  double dim2;
    public  Figure(double dim1,double dim2){
    this.dim1=dim1;
    this.dim2=dim2;
    }
    public double area(){
        System.out.println("父类里的方法,没有实际意义");
         return 0;
    }
}
class Rectangle extends Figure{
    public Rectangle(double dim1, double dim2) {
        super(dim1, dim2);
    }
    public double area(){
        System.out.println("长方形的面积");
        return this.dim1 * this.dim2;
    }
}

class Tirangle extends Figure{
    public Tirangle(double dim1,double dim2){
        super(dim1,dim2);
    }
    public double area(){
        System.out.println("三角形的面积");
        return this.dim1 * this.dim2 /2;
    }
}

抽象类

抽象类使用abstract关键字来修饰,如果一个方法用abstract关键字来修饰表示这个方法是一个抽象方法。

抽象方法必须存在于抽象类中,子类如果继承抽象类时,必须要重写父类所有的抽象方法。抽象类不能被实例化

//抽象类
public class Anmial{
 public static void main(String [] args){
   Square square=new Square(2,2);
   System.out.println("正方形的面积为:"+square.area());
   Triangle triangle=new Triangle(2,2);
   System.out.println("三角形面积为"+triangle.area());
 }
}


abstract  class Shape{
 public int width;
 public int height;
  public Shape(int w,int h){
      this.width=w;
      this.height=h;
  }
  public abstract double area();
}
class Square extends  Shape{
    public Square(int w, int h) {
        super(w, h);
    }

    public double area(){
        return super.width * super.height;
    }
}
class Triangle extends Shape{
    public Triangle(int w,int h){
         super(w,h);
    }
    public double area(){
        return 0.5*super.width*super.height;
    }
}

接口

接口是一种特殊的类,接口里没有执行体,有的只是全局常量和公共的方法

接口使用interface关键字定义,一个接口可以继承多个接口

public class Anmial{
 public static void main(String [] args){
    MathClass mathClass=new MathClass(1,2);
    System.out.println("1和2的和是"+mathClass.sum());
    System.out.println("1和2比较大的是"+mathClass.maxNum());

 }
}
interface  IMath{
    public int sum();
    public int maxNum();
}
class MathClass implements IMath{
    private  int num1;
    private  int num2;
    public MathClass(int num1,int num2){
        this.num1=num1;
        this.num2=num2;
    }
    public int sum(){
      return this.num1+this.num2;
    }
    public int maxNum(){
         if(this.num1>this.num2){
             return this.num1;
         }else{
             return this.num2;
         }
    }
}

内部类

java里在类内部,可以再定义一个类,内部类分为实例内部类,静态内部类,成员内部类

// testDemo就是一个内部类
public class Anmial{
 public static void main(String [] args){
    Anmial.testDemo testdemo =new Anmial().new testDemo();
    System.out.println(testdemo.getSum(1,2));

 }
 private class testDemo{
     public int getSum(int a,int b){
         return a+b;
     }
 }
}

实例内部类

实例内部类是指没有static修饰的内部类。

 在外部类的静态方法和,外部类以外的其他类中,必须通过外部类的实例创建内部类的实例。
 如果是多层嵌套,则内部类可以访问外部类的所有成员。
 在内部类中不能定义static,除非带上final

静态内部类

静态内部类是指,内部类是用static修饰的内部类。

创建静态内部类的实例时,不需要创建外部类的实例。

静态内部类可以定义静态,

外部类以外的其他类,需要通过完整的类名访问内部类里的静态。

静态内部类可以直接访问外部类的静态,如果访问非静态需要通过外部类的实例去访问。

局部内部类

局部内部类是指在方法里定义一个类

局部类只在当前的方法内有效

局部内部类中不能定义静态

局部内部可以访问外部类的所有成员
public class persion{
 public void test(){
    class Inner{

    }
    //Inner就是局部内部类
 }
}

Lambda表达式(闭包)


// ()->{} 这个就是Lanbda表达式(跟Es6的箭头函数有点像)
public class bibao {
 public static Math math(char opr){
    Math result;
    if(opr == '+'){
       result=(int a,int b)->{
           return a+b;
       };
    }else{
        result =(int a,int b)->{
            return a-b;
        };
    }
    return result;
 }
 public static void main(String [] args){
     int n1=10;
     int n2=5;
     Math f1=math('+');
     Math f2=math('-');
     System.out.println(f1.calculateInt(n1,n2));
     System.out.println(f2.calculateInt(n1,n2));
 }
}
interface Math{
    int calculateInt(int a,int b);
}

常见的用途

作为参数传递

public class bibao {
 public static void display(S s,int a,int b){
     System.out.println(a+"+"+b+"的结果是"+ s.sum(a,b));
 }
 public static void main(String [] args){
   display((a,b)->a+b,10,6);
   display((a,b)->a+b,60,6);
 }
}

interface  S{
 int sum(int a,int b);
}

访问变量

访问非静态变量需要,用this访问

public class bibao {
    public static int g=10;
 public static void display(S s,int a,int b){
     System.out.println(a+"+"+b+"的结果是"+ s.sum(a,b));
 }
 public static void main(String [] args){
   display((a,b)->a+b+g,10,6);
   display((a,b)->a+b+g,60,6);
 }
}

方法引用

public class bibao {
 public static void display(S s,int a,int b){
     System.out.println(a+"+"+b+"的结果是"+ s.sum(a,b));
 }
 public static void main(String [] args){
    display(Demos :: add,10,20);
    Demos demos=new Demos();
    display(demos::sub,20,20);
    //这就是方法引用
 }
}

class Demos{
    public static int add(int a,int b){
        return a+b;
    }
    public int sub(int a,int b){
        return a-b;
    }
}
interface  S{
 int sum(int a,int b);
}