zoukankan      html  css  js  c++  java
  • Java基础之继承

    继承的格式

    【修饰符】 class 父类 {
    	...
    }
    
    【修饰符】 class 子类 extends 父类 {
    	...
    }

    继承特点:成员变量

    私有化(private)

    • 父类中的成员,无论是公有(public)还是私有(private),均会被子类继承。

    • 子类虽会继承父类私有(private)的成员,但子类不能对继承的私有成员直接进行访问,可通过继承的公有方法进行访问(setxxx&getxxx)。如图所示:

    class Animal {
        // 定义name属性
    	private String name; 
        // 定义age属性
        public int age;
    	// 定义动物的吃东西方法
    	public void eat() {
    		System.out.println(age + "岁的" + name + "在吃东西");
    	}
    }
    /*
     * 定义猫类Cat 继承 动物类Animal
     */
    class Cat extends Animal {
    	// 定义一个猫抓老鼠的方法catchMouse
    	public void catchMouse() {
    		System.out.println("抓老鼠");
    	}
    }
    
    /*
     * 定义测试类
     */
    public class ExtendDemo01 {
    	public static void main(String[] args) {
            // 创建一个猫类对象
    		Cat cat = new Cat();
          
            // 为该猫类对象的name属性进行赋值
    		//t.name = "Tom";// 编译报错
          
          	// 为该猫类对象的age属性进行赋值
    		t.age = 2;
            
            // 调用该猫的catchMouse()方法
    		t.catchMouse();
    		
          	// 调用该猫继承来的eat()方法
          	t.eat();
    	}
    }
    

    成员变量不重名

    如果子类父类中出现不重名的成员变量,这时的访问是没有影响的

    成员变量重名

    如果子类父类中出现重名的成员变量,这时的访问是有影响的

    class Fu {
    	// Fu中的成员变量。
    	int num = 3;
    }
    
    class Zi extends Fu {
    	// Zi中的成员变量
    	int num = 4;
    	public void show() {
    		// 访问的num到底是子类还是父类?
    		System.out.println("num = " + num);
    
    	}
    }
    class ExtendsDemo03 {
    	public static void main(String[] args) {
          	// 创建子类对象
    		Zi z = new Zi(); 
          	// 调用子类中的show方法
    		z.show(); 
    	}
    }
    演示结果:
    num = 4
    

    子父类中出现了同名的成员变量时,在子类中需要访问父类中非私有成员变量时,需要使用super 关键字,修饰父类成员变量,类似于之前学过的 this  

    承接上例子类方法需要修改,代码如下:

    class Zi extends Fu {
    	// Zi中的成员变量
    	int num = 6;
    	public void show() {
    		//访问父类中的num
    		System.out.println("Fu num=" + super.num);
    		//访问子类中的num
    		System.out.println("Zi num=" + this.num);
    	}
    }
    演示结果:
    Fu num = 5
    Zi num = 6
    

    继承的特点二:成员方法

    成员方法不重名

    如果子类父类中出现不重名的成员方法,这时的调用是没有影响的。对象调用方法时,会先在子类中查找有没有对应的方法,若子类中存在就会执行子类中的方法,若子类中不存在就会执行父类中相应的方法

    成员方法重名——重写(Override)

    如果子类父类中出现重名的成员方法,这时的访问是一种特殊情况,叫做方法重写 (Override)。

    class Fu {
    	public void show() {
    		System.out.println("Fu show");
    	}
    }
    class Zi extends Fu {
    	//子类重写了父类的show方法
    	public void show() {
    		System.out.println("Zi show");
    	}
    }
    public class ExtendsDemo05{
    	public static void main(String[] args) {
    		Zi z = new Zi();
         	// 子类中有show方法,只执行重写后的show方法
    		z.show();  // Zi show
    	}
    }
    

    在父子类的继承关系当中,创建子类对象,访问成员方法的规则:
    创建的对象是谁,就优先用谁,如果没有则向上找。

    注意事项:
    无论是成员方法还是成员变量,如果没有都是向上找父类,绝对不会向下找子类的。

    重写(Override)
    概念:在继承关系当中,方法的名称一样,参数列表也一样。

    重写(Override):方法的名称一样,参数列表【也一样】。覆盖、覆写。
    重载(Overload):方法的名称一样,参数列表【不一样】。

    方法的覆盖重写特点:创建的是子类对象,则优先用子类方法。

    方法覆盖重写的注意事项:见下面

      

    重写的应用

    子类可以根据需要,定义特定于自己的行为。既沿袭了父类的功能名称,又根据子类的需要重新实现父类方法,从而进行扩展增强。比如新的手机增加来电显示头像的功能,代码如下:

      

    class Phone {
    	public void sendMessage(){
    		System.out.println("发短信");
    	}
    	public void call(){
    		System.out.println("打电话");
    	}
    	public void showNum(){
    		System.out.println("来电显示号码");
    	}
    }
    
    //智能手机类
    class NewPhone extends Phone {
    	
    	//重写父类的来电显示号码功能,并增加自己的显示姓名和图片功能
    	public void showNum(){
    		//调用父类已经存在的功能使用super
    		super.showNum();
    		//增加自己特有显示姓名和图片功能
    		System.out.println("显示来电姓名");
    		System.out.println("显示头像");
    	}
    }
    
    public class ExtendsDemo06 {
    	public static void main(String[] args) {
          	// 创建子类对象
          	NewPhone np = new NewPhone();
            
            // 调用父类继承而来的方法
            np.call();
          
          	// 调用子类重写的方法
          	np.showNum();
    
    	}
    }
    

    注意事项

    1. 必须保证父子类之间方法的名称相同,参数列表也相同。 @Override:写在方法前面,用来检测是不是有效的正确覆盖重写。 这个注解就算不写,只要满足要求,也是正确的方法覆盖重写。

    2. 子类方法的返回值类型必须【小于等于】父类方法的返回值类型(小于其实就是是它的子类)。 小扩展提示:java.lang.Object类是所有类的公共最高父类(祖宗类),java.lang.String就是Object的子类。

      注意:如果返回值类型是基本数据类型和void,那么必须是相同

    3. 子类方法的权限必须【大于等于】父类方法的权限修饰符。 小扩展提示:public > protected > 缺省 > private 备注:缺省不是汉字缺省,而是什么都不写,留空。

    4. 几种特殊的方法不能被重写

      • 静态方法不能被重写

      • 私有等在子类中不可见的方法不能被重写

      • final方法不能被重写

    继承的特点三:构造方法

    首先我们要回忆两个事情,构造方法的定义格式和作用。

    1. 构造方法的名字是与类名一致的。所以子类是无法继承父类构造方法的。

    2. 构造方法的作用是初始化成员变量的。所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构造方法中默认有一个super() ,表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。代码如下:

    class Fu {
      private int n;
      Fu(){
        System.out.println("Fu()");
      }
    }
    class Zi extends Fu {
      Zi(){
        // super(),调用父类构造方法
        super();
        System.out.println("Zi()");
      } 
    }
    public class ExtendsDemo07{
      public static void main (String args[]){
        Zi zi = new Zi();
      }
    }
    输出结果:
    Fu()
    Zi()
    

    如果父类没有无参构造怎么办?

    此时子类代码报错。

    解决办法:在子类构造器中,用super(实参列表),显示调用父类的有参构造解决。

    构造器的知识回顾

    1、要创建一个类的实例对象,必须调用一个对象的构造器,来完成类的实例初始化过程。实例初始化过程就是为实例变量赋初始值的过程。
    2,当一个对象被创建时候,构造方法用来初始化该对象,给对象的成员变量赋初始值。
    3,无论你与否自定义构造方法,所有的类都有构造方法,因为Java自动提供了一个无参数构造方法,一旦自己定义了构造方法,Java自动提供的默认无参数构造方法就会失效。 

    示例

    public class Person {
    	private String name;
    	private int age;
    	public Person(String name, int age) {
    		super();
    		this.name = name;
    		this.age = age;
    	}
    	//其他成员方法省略
    }
    
    
    public class Student extends Person{
    	private int score;
    
    	public Student(String name, int age) {
    		super(name, age);
    	}
    	public Student(String name, int age, int score) {
    		super(name, age);
    		this.score = score;
    	}
    	
    	//其他成员方法省略
    }
    

    super

    父类空间优先于子类对象产生

    在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。目的在于子类对象中包含了其对应的父类空间,便可以包含其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员。代码体现在子类的构造方法调用时,一定先调用父类的构造方法

    public class Person {
    	private String name;
    	private int age;
    	//其他代码省略
    }
    public class Student extends Person{
    	private int score;
    	//其他成员方法省略
    }
    public class Test{
        public static void main(String[] args){
        	Student stu = new Student();
        }
    }
    

      

    super和this的含义

    • super :代表父类的存储空间标识(可以理解为父亲的引用)。

      • 通过super找成员变量和成员方法时,直接从父类空间(包含父类的父类继承的)找

      • super()或super(实参列表)只能从直接父类找

      • 通过super只能访问父类在子类中可见的(非private,跨包还不能是缺省的)

    • this :代表当前对象的引用

      • 通过this找成员变量和成员方法时,先从当前类中找,没有的会往上找父类的。

      • 但是this()或this(实参列表)只会在本类中找

    注意:super和this都不能出现在静态方法和静态代码块中,因为super和this都是存在与对象中的

    super的用法

    1、super.成员变量

    在子类对象中访问父类空间的成员变量,即访问从父类继承的在子类中仍然可见的成员变量

    1)子类没有与父类重名的成员变量  

    public class Test{
        public static void main(String[] args){
            Son s = new Son();
            s.test();
        }
    }
    class Father{
        int a = 10;
    }
    class Son extends Father{
        public void test(){
            System.out.println(super.a);//10
            System.out.println(this.a);//10
            System.out.println(a);//10
        }
    }
    View Code

    2)子类有与父类重名的成员变量

    public class Test{
        public static void main(String[] args){
            Son s = new Son();
            s.test();
        }
    }
    class Father{
        int a = 10;
    }
    class Son extends Father{
        int a = 20;
        public void test(){
            System.out.println(super.a);//10
            System.out.println(this.a);//20
            System.out.println(a);//20
        }
    }
    View Code

    3)方法有局部变量与成员变量重名

    public class Test{
        public static void main(String[] args){
            Son s = new Son();
            s.test(30);
        }
    }
    class Father{
        int a = 10;
    }
    class Son extends Father{
        int a = 20;
        public void test(int a){
            System.out.println(super.a);//10
            System.out.println(this.a);//20
            System.out.println(a);//30
        }
    }
    View Code

    2、super.成员方法

    在子类对象中访问从父类继承的在子类中仍然可见的成员方法

    1)子类没有重写方法  

    public class Test{
        public static void main(String[] args){
            Son s = new Son();
            s.test();
        }
    }
    class Father{
        public void method(){
            System.out.println("aa");
        }
    }
    class Son extends Father{
        public void test(){
            method();//aa
            this.method();//aa
            super.method();//aa
        }
    }
    View Code

    2)子类重写父类的方法

    public class Test{
        public static void main(String[] args){
            Son s = new Son();
            s.test();
        }
    }
    class Father{
        public void method(){
            System.out.println("aa");
        }
    }
    class Son extends Father{
        public void method(){
            System.out.println("bb");
        }
        public void test(){
            method();//bb
            this.method();//bb
            super.method();//aa
        }
    }
    View Code

    super()或super(实参列表)

    this(...)    	--    本类的构造方法
    super(...)   	--    父类的构造方法
    

    子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super()。

    super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现。

      

    final

    1、修饰类

    表示这个类不能被继承,没有子类

    final class Eunuch{//太监类
    	
    }
    

    2、修饰方法

    表示这个方法不能被子类重写

    class Father{
    	public final void method(){
    		System.out.println("father");
    	}
    }
    

    3、声明常量

    某个变量如果使用final修饰,那么它的值就不能被修改,即常量

    final可以修饰成员变量(静态的类变量和非静态的实例变量)和局部变量

    如果某个成员变量用final修饰后,没有set方法,并且必须有显式赋值语句,不能使用成员变量默认值

    被final修饰的常量名称,一般都有书写规范,所有字母都大写

    public class Test{
        public static void main(String[] args){
            final int MIN_SCORE = 0;
            final int MAX_SCORE = 100;
        }
    }
    class Chinese{
        public static final String COUNTRY = "中华人民共和国";    
        private final String BLOODTYPE = "A";//显示赋值
        private final String CARDID;//如果没有显示赋值,必须保证在
        private String name;
        public Chinese(String cardId, String name) {
            super();
            this.CARDID = cardId;
            this.name = name;
        }
        public Chinese() {
            super();
            CARDID = "000000000000000000";//必须在所有构造器中进行赋值
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        //final修饰的没有set方法
        public static String getCountry() {
            return COUNTRY;
        }
        public String getCardId() {
            return cardId;
        }
        public String getBloodType() {
            return bloodType;
        }
    }
    View Code
    本文为原创文章,转载请标明出处
  • 相关阅读:
    Android游戏开发22:Android动画的实现J2me游戏类库用于Android开发
    android sqlite SQLiteDatabase 操作大全 不看后悔!必收藏!看后精通SQLITE (第三部分,完整代码)
    使用OGR创建dxf格式矢量数据
    mysql 数据库引擎 MyISAM InnoDB 大比拼 区别
    android sqlite SQLiteDatabase 操作大全 不看后悔!必收藏!看后精通SQLITE (第二部分)
    mysql 更改数据库引擎
    android sqlite SQLiteDatabase 操作大全 不看后悔!必收藏!看后精通SQLITE (第一部分)
    android 数字键盘使用
    MySQL Innodb数据库性能实践
    eclipse : Error while performing database login with the driver null
  • 原文地址:https://www.cnblogs.com/harden13/p/14526918.html
Copyright © 2011-2022 走看看