咕噜咕噜哈里  

1.类的继承

    类的继承是面向对象程序设计的一个重要特点,通过继承可以实现代码的复用,被继承的类称为父类或超类,由继承而得到的类称为子类。

一个父类可以同时拥有多个子类,但由于Java语言不支持多重继承,所以一个类只能有一个直接父类。父类实际上是所有子类的公共成员的集合。,

而每一个子类则是父类的特殊化,是对公共成员变量和方法在功能、内涵方面的扩展和延伸。

    在Java语言中有一个名为 java.lang.Object 的特殊类,所有的类都是直接或间接地继承该类而得到的。

①子类的创建

    Java语言中类的继承是通过 extends 关键字来实现的,在定义时若使用 extends 关键字指出新定义类的父亲,就是在两个类之间建立了继承关系。

新定义的类称为子类,它可以从父类那里继承所有非私有成员作为自己的成员。通过在类的声明时使用 extends 关键字来创建一个类的子类,其格式如下:

class  SubClass extends SuperClass{
      .......
}

 

    上述语句把 SubClass 声明为类 SuperClass 的直接子类,如果 SuperClass 又是某个类的子类,则 SubClass 同时也是该类的间接子类。

②子类的构建方法

例子:类的继承,创建个人类 Person ,再以该类为父类创建一个学生子类 Student。

class Person{
   private String name;
   private int age;
   public Person(){
       System.out.println("调用了个人类构造方法 Person()");
   }
   public void setNameAge(String name,int age){
       this.name = name;
       this.age = age;
   }
   public void show(){
       System.out.println("姓名:"+name +"  年龄+:"+age);
   }
}
class Student extends Person(){    //定义 Student 类,继承自 Person 类
    prinvate String department;
    public Student(){     //定义 Student 类的构造方法
       System.out.println("调用了学生类的构造方法 Student()");
  }
   public void setDepartment(String dep){
       department = dep;
       System.out.println("我是"+ departement + "的学生");
   }
}
public class {
    Student stu = new Student();    //创建 Student 对象
    stu.setNameAge("张小三",21); //调用父类的 setNameAge() 方法
    stu.show();     //调用父类的 show() 方法
    stu.setDepartment("计算机系");     //调用子类setDepartment() 方法
}

说明:Java 程序在执行子类的构造方法前,会先调用父类中没有参数的构造方法,其目的是为了帮助继承自父类的成员做初始化的操作。

③调用父类中特定的构造方法

      通过 super() 语句来调用父类特定的构造方法

例子:以 Person 作为父类,创建学生子类 Student,并在子类中调用父类中某指定的构造方法。  

class Person{
    private String name;
    private int age;    //定义 Person 的无参构造方法
    public Person(){
        System.out.println("调用了 Person 类的无参构造方法");
   }
    public Person(String name,int age){    //定义 Person 类的有参构造方法
        System.out.println("调用了 Person 类的有参构造方法");
         this.name = name;
         this.age = age;
    }
    public void show(){
         System.out.println("姓名: " + name "   年龄:"+ age);
   } 
}
class Student extends Person{   //定义继承来自 Person 类的子类 Student
     private String department;
     public Student(){      //定义 Student 类的无参构造方法
        System,out.println("调用了学生了的无参构造方法 Student()");
   }
public Student(String name,int age,String dep){   //定义 Student 类的有参构造方法
     super(name,age);    //调用父类的有参构造方法,在第10行定义的     departement = dep;
     System.out.println("我是"+department + "的学生");
     System.out.printlin("调用了学生类的有参构造方法 Stunden(String name,int age,String dep)")
}
}
public class{
    public static void main(String[] args){
        Student stu1 = new Student();     //创建对象,并调用无参构造方法
        Student stu2 = new Student("李小四",23,“信息系”);   //创建对象,并调用有参构造方法
         stu1.show();
         stu2.show();
   }
}

注意:1.super() 与 this() 的功能相似,但 super() 是从子类的构造方法调用父类的构造方法,而 this() 则是在同一个类内调用其他的构造方法。 

 2.super () 与 this() 均必须放在构造方法内的第一行,正因如此,super() 与 this() 无法同时存在同一个构造方法内。

2.在子类中访问父类成员

     在子类中使用 super 不但可以访问父类的构造方法,还可以访问父类的成员变量和成员方法,但 super 不能访问在子类中添加的成员。在子

类中访问父类成员的格式如下:super.变量名;super.方法名();

     另外,由于在子类中不能继承父类中的 private 成员,所以无法在子类中(类外)访问父类中的这种成员。但如果将在父类中的成员声明为 protected(保护)

成员的,而非 private 成员,则 protected 成员不仅可以在父类中直接访问,同时也可以在其子类中访问。

例子:在学生子类 Student 中访问父类 Person 的成员。

 

class Person{
    protected String name;   //声明被保护的成员变量
    protected int age;
    public Person(){}    //定义 Person 类的“不做事”的无参构造方法
    public Person (String name,int age){   //定义 Person 类的有参构造方法
         this.name = name;
         this.age = age;
    }
    protected void show(){    //定义被保护的成员方法
         System.out.println("姓名:"+name+"  年龄:"+age);
   }
}
class Student extends Person{    //定义子类 Student ,其父类为 Person 
    private String departement;   //声明私有数据成员
    int age = 20;   //新添加了一个与父类的成员变量 age 同名的成员变量
    public Student (String xm,String dep){   //定义 Student 类的有参构造方法
       name = xm;    //在子类中直接访问父类 protected 成员 name
       departement = dep;
       super.age = 25;    //利用 super 关键字将父类的成员变量 age 赋值为 25
       System.out.println("子类 student 中的成员变量 age = "+age);
       super.show();  //去掉 super 而只写 show()也可
       System.out.println("系别:" +department);
   }
}
public class {
    public static void main(String[] args){
       Student stu = new Student("李小四",“信息系”);
   }
}

3.覆盖 (子类中新增与父类同名的成员)

     ①覆盖子类的方法

      在子类中重新定义已有的方法时,应保持与父类中完全相同的方法头声明,即应与父类中被覆盖的方法有完全相同的方法名、

返回值类型和参数列表,否则就不是方法的覆盖,而是子类定义自己的父类无关的方法,父类的方法未被覆盖,所以仍然存在。

也就是说,子类继承父类中所有可被访问的成员方法时,如果子类的方法头与父类中的方法头完全相同,则不能继承,此时子类

的方法就是覆盖父类的方法。

    注意:子类中不能覆盖父类中声明为final或static的方法。

例子:以个人类 Person 为父类,创建学生子类 Student,并用子类中的方法覆盖父类的方法。

class Person{
   protected String name;
   protected int age;
   public Person(String name,int age){    //定义 Person 类的构造方法
       this.name = name;
       this.age = age;
   }
   protected void show(){
      System.out.println("姓名:"+ name +"年龄:"+ age);
  }
}
class Student extends Person{    //定义子类 Student ,其父类为 Person
     private String department;
     public Student(String name,int age,String dep){
         super(name,age);
         departement = dep;
   }
protected void show(){   //覆盖父类 Person 中的同名方法
     System.out.println("系别:"+ department);
}
}
public class{
    public static void main(String[] args){
        Student stu = new Student("王永涛",24,“电子”);
        stu.show();
   }
}


系别:电子

②不可被继承的成员最终类

    如果父类成员不希望被子类的成员所覆盖可以将他们声明为 final.如果用 final 来修饰成员变量,

则说明成员变量是最终变量,即常量,程序中的其他部分都可以访问,但不能修改。

③Object类

    如果某个类没有使用 extends 关键字,则该类默认为 java.lang.Object 类的子类。

4.抽象类

     在java中创建专门的类作为父类,这种类被称为抽象类(abstract class)。抽象类的作用有点类似“模板”,其目的是根据它的格式

来创建和修改新的类。但并不能直接由抽象类创建对象,只能通过抽象类派生出新的子类,再由其子类来创建对象。

     抽象类是以修饰符 abstract 修饰的类。定义抽象类的语法格式如下:

      

abstract class 类名{
   声明成员变量;
   返回值的数据类型  方法名(参数表){
            ......
   }
           .....
     abstract 返回值的数据类型  方法名(参数表);———抽象方法。在抽象方法里,不能定义方法体。 
}

注意:abstract 不能与 private、static、final或native并列修饰同一个方法。 

例子:在抽象类 Base,基础上派生出一个矩形类 Rectangle,新增成员变量 width和 height ,分别代表矩形的长和宽,采用构造方法给成员变量赋值,

并实现抽象类中的抽象方法,在声明一个主类,创建一个矩形类的对象,该对象的数据成员(color,width,height)的取值为(“red”,8,3),在屏幕上

显示出该矩形的成员变量值,并求矩形的面积和周长。

class Rectangle extends Base{
   double width;
    double height;
    public Rectangle(String s,double w,double h){
        super(s);
        width = w;
        height = h;
   }
public double area(){
    return width*height;
   }
public double perimeter(){
   return(width + height)*2;
  }
public void display(){
   System.out.pritln(color +" "+width+","+height);
  }
public static void main(String[] args){
   Base m = new Rectangle("red",8,3);
   m.display();
   System.out.println("面积="+m.area());
   System.out.println("周长="+m.perimeter());
}
}

5.接口

    接口是(interface)是java语言提供的另一种重要功能,它的结构与抽象类相似。本身也具有数据成员、抽象方法、默认方法和静态方法,

但它与抽象类有下列不同。

     (1)接口的数据成员都是静态的且必须初始化,即数据成员必须是静态常量。

     (2)接口中除了声明抽象方法外,还可以定义静态方法和默认方法,但不能定义一般方法。

①接口的定义:

 

②接口的实现与引用

     接口实现的语法格式:

class 类名称 implement 接口名表{

                       ........       
 
}

一个类要实现一个接口时,应注意一下问题:

     (1)如果实现某接口的类不是 abstract 的抽象类,则在类的定义部分必须实现指定接口的所有抽象方法,即非抽象类中不存在抽象方法。

     (2)一个类在实现某接口的抽象方法时,必须使用完全相同的方法头,否则只是在定义一个新方法,而不是实现已有的抽象方法。

     (3)接口中抽象方法的访问控制修饰符都已指定为 pulic ,所以类在实现方法时,必须显式地使用 public 修饰符,否则将被系统警告为缩小了接口中

定义方法的访问控制范围。

      (4)  与类一样,每个接口都被编译成独立的扩展名为.class 的字节码文件。

例子:计算圆柱的底面积和体积,通过类MainClass 继承父类 Cylinder 并实现接口 Action 来达到目的。

interface Action{
   static  final double P = 3.14;
   abstract double s();   //求底面积
   abstract double v();   //求体积
} 
class Cylinder{
   protected double radius;   //圆柱底面半径
   protected double height;
   public Cylinder(double r,double h){
       radius = r;
       height = h;
   }
} 

③利用接口实现类的多重继承(只能继承一个类,但可以实现多个接口)

例子:利用接口实现类的多重继承

 

package ch08; 
interface Face1{  
    final double PI=3.14; 
    abstract double area(); 
} 
interface Face2{  
    abstract void setColor(String c); 
} 
interface Face3{  
    abstract void volume(); 
}  
public class Cylinder implements Face1,Face3{  //Cylinder 类实现并继承两个接口  
    private double radius;  
    private int height;  
    protected String color;  
    public Cylinder(double r,int h){   
        radius=r;   
        height=h;  
    }  
    public double area(){   
        return PI*radius*radius;  
    }  
    public void setColor(String c){   
        color=c;   
        System.out.println("颜色:"+color);  
    }  
    public void volume(){   
        System.out.println("圆柱体体积="+area()*height);  
    }  
    public static void main(String[] args){   
        Cylinder volu=new Cylinder(3.0,2);   
        volu.setColor("红色");   
        volu.volume();  
    } 
} 

④接口中静态方法和默认方法

     接口中的静态方法与普通类中静态方法的定义相同。接口中的静态方法不能被子类接口继承,也不能被实现该接口的类继承。

对接口中静态方法的访问,可以通过接口名直接访问,可以通过接口名进行访问,即“接口名.静态方法名()”的形式进行调用。接口中的

默认方法虽然有方法体,可是不能通过接口名直接调用,但可以通过接口实现类的实例进行访问,即“对象名.默认方法名()”形式。

例子:在接口 Face 中定义默认方法、静态方法和抽象方法,在接口的实现类中进行相应的方法调用。

interface Face{
   final static double PI = 3.14;   //定义常量
   public default double area(int r){    //定义默认方法
      return r * r * PI;
 }
abstract double volume(int r,double h){   //声明抽象方法
public  static show(){                             //定义静态方法
       return "我是 Face 接口中的静态方法";
    }
  }
public class  App8_14  implements Face{   //定义主类App8_14 并实现接口 Face
     public double volume(int r,double h){   //实现接口中的方法
         return area(r) * h;                         //调用接口中的默认方法 area()
     }
public static void main(String[] args){
        System.out.println(Face.show());
        App8_14 ap = new App8_14;   //直接使用接口名调用接口的静态方法
        System.out.println("圆柱体体积为:"+ap.volume(1,2.0));
    }
  }
}

我是 Face 接口中的静态方法
圆柱体体积为:6.28

⑤解决接口中多重继承中名字冲突问题

   如果子接口中定义了与父接口同名的常量或者相同名称的方法,则父接口中的常量被隐藏,方法被覆盖。但在接口的多重继承中可能存在常量名或方法名称重复的问题,

即名字冲突问题。对于常量若名称不冲突,子接口可以继承多个父接口中的常量,如果多个父接口中有同名的常量,则子接口不能继承,但子接口中可以定义一个同名的常量。

对于多个父接口中存在同名的方法时,此时必须通过特殊的方式加以解决。
    如果一个类实现了两个接口,其中一个接口中有默认方法,另一接口中也有一个名称和参数都相同的方法(默认或抽象方法),此时发生方法名冲突。如果出现这种情况,

编译器就不知道该继承哪个方法,所以编译报错。要解决方法名冲突问题,可以在接口的实现类中提供同名方法的一个新实现,引用其中一个父接口中的默认方法,

这种引用方式称为委托某父接口中的默认方法,委托方式为:接口名. super .默认方法名 () 。

posted on 2022-03-12 14:11  咕噜咕噜哈里  阅读(154)  评论(0编辑  收藏  举报