JAVA——子类与继承

一:子类与父类:

       在编写一个类时,若某个类中有所需要的成员变量和方法,如果我们想复用这个类中的成员和方法,那么可以将编写的类定义为这个类的子类,子类可以让我们不必一切“从头做起”。

       继承是一种由已有的类创建新类的机制。利用继承,可以先定义一个共有属性的一半了in,根据该一般类再定义具有特殊属性的子类,子类继承一般类的属性和行为,并根据需要增加她自己新的属性和行为。

       由继承得到的类称为子类,被继承的类称为父类(超类)。JAVA不支持多重继承,子类只能有一个父类,但父类可以有多个或者零个子类。

❶子类:在类的声明中,通过使用关键字extends来定义一个类的子类,格式为:

class 子类名 extends 父类名{
           ...
   }

例如:

class people extends object{   //people为子类,object为父类
    ...
    }

 ❷类的树形结构:

        JAVA的类按继承关系形成树形结构(将类看作树上的结点).在这个树形结点中,根节点是object类,object是所有类的祖先。如果一个类的声明中没有使用extends关键字,这个类被系统默认为是Object的子类,即“class A”与“class A extends Object”是等同的。

public class People { 
    int age,leg = 2,hand = 2;
    protected void showPeopleMess() {
       System.out.printf("%d岁,%d只脚,%d只手\t",age,leg,hand);
    }    
}
public class Student extends People {
   int number;
   void tellNumber() {
       System.out.printf("学号:%d\t",number); 
   }
   int add(int x,int y) {
      return x+y;
   } 
} 
public class UniverStudent extends Student {
   int multi(int x,int y) {
      return x*y;
   }  
}
   public static void main(String args[]) {
      Student zhang = new Student();
      zhang.age = 17;           //访问继承的成员变量
      zhang.number=100101;
      zhang.showPeopleMess();  //调用继承的方法
      zhang.tellNumber();        
      int x=9,y=29;
      System.out.print("会做加法:");
      int result=zhang.add(x,y);
      System.out.printf("%d+%d=%d\n",x,y,result);
      UniverStudent geng = new UniverStudent();
      geng.age = 21;          //访问继承的成员变量
      geng.number=6609;
      geng.showPeopleMess();  //调用继承的方法
      geng.tellNumber();        //调用继承的方法
      System.out.print("会做加法:");
      result=geng.add(x,y);      //调用继承的方法
      System.out.printf("%d+%d=%d\t",x,y,result);
      System.out.print("会做乘法:");
      result=geng.multi(x,y);
      System.out.printf("%d×%d=%d\n",x,y,result); 
   }

二:子类的继承性:

        类可以有两种重要的成员:成员变量和方法。所谓子类继承父类的成员变量作为自己的一个成员变量,就像他们是在子类中被直接声明,可以被子类中自己定义的任何一种实例方法调用。如果子类中定义的实例方法不能操作父类的某个成员变量,该成员变量就没有被子类继承。

❶:子类和父类在同一包中的继承性:

        如果子类和父类在同一个包中,那么子类自然的继承了父类中不是private的成员变量和方法作为自己的成员变量和方法。继承的成员变量或方法的访问权限保持不变。

❷:子类和父类不在同一包中的继承性:

       当子类和父类不在同一包中时,子类只能继承父类中protected和public访问权限的成员变量作为子类的成员变量;同时,子类只能继承父类中的protected和public访问权限的方法作为子类的方法。

三:子类与对象:

❶子类对象的特点:

当用子类的构造方法创建一个子类的对象时,不仅子类中被声明的成员变量被分配了内存,而且父类的成员变量也被分配了内存空间,但只将其中的一部分,即子类继承的那部分成员变量,作为分配给子类对象的变量。子类不继承父类的私有变量。如果子类和父类不在同一包中,子类不继承父类的友好成员变量。

class People {
    private int averHeight = 166;
    public int getAverHeight() {
       return averHeight;
    }
}
class ChinaPeople extends People {    //ChinaPeople是People 的子类,继承父类具有的方法和属性,相当于子类中一共有两个属性,三个方法;
     int height;
     public void setHeight(int h) {
          height = h+averHeiht; // 非法,因为父类的averHeiht的访问权限是私有的;子类没有继承averHeiht
          height = h;
     }
     public int getHeight() {
        return height;
     }
}
  public static void main(String args[]) {
      ChinaPeople zhangSan = new ChinaPeople();
      System.out.println("子类对象未继承的averageHeight的值是:"+zhangSan.getAverHeight());
      zhangSan.setHeight(178);
      System.out.println("子类对象的实例变量height的值是:"+zhangSan.getHeight());
  }  

❷:关于instanceof运算符

instanceof运算符是JAVA独有的双目运算符,其左边的操作元是对象,右边的操作元是类。当左边的操作元是右边的类或者其子类所创建的对象时,instanceof运算符的结果是true,否则是false.。

四:成员变量的隐藏和方法重写:

❶成员变量的隐藏:在编写子类时,我们仍然可以声明成员变量,一种特殊的情况就是,所声明的成员变量的名字和从父类继承的成员变量的名字相同,在这种情况下,子类就会隐藏所继承的成员变量.

 public class Goods {
    public double weight;
    public void oldSetWeight(double w) {
       weight=w;
       System.out.println("double型的weight="+weight);
    }
    public double oldGetPrice() {
        double price = weight*10;
        return price;
    }
}
public class CheapGoods extends Goods {
    public int weight;
    public void newSetWeight(int w) {
       weight=w;
//       System.out.println("int型的weight="+weight);
    }
    public double newGetPrice() {
        double price = weight*10;
        return price;
    }
}
public static void main(String args[]) {
     CheapGoods cheapGoods=new CheapGoods();
     //cheapGoods.weight=198.98;   //是非法的,因为子类对象的weight已经是int型
     cheapGoods.newSetWeight(198);
     System.out.println("对象cheapGoods的weight的值是:"+cheapGoods.weight);
     System.out.println("cheapGoods用子类新增的优惠方法计算价格:"+
                         cheapGoods.newGetPrice());
     cheapGoods.oldSetWeight(198.987);  //子类对象调用继承的方法操作隐藏的double型变量weight
     System.out.println("cheapGoods使用继承的方法(无优惠)计算价格:"+
                          cheapGoods.oldGetPrice());
  }  

❷方法重写:

子类通过重写可以隐藏所继承的方法.

⑴重写的语法规则:

●子类中定义一个方法,这个方法的类型额父类的方法的类型一致或者是父类的方法的类型的子类;

●相同的方法名称,相同的参数列表.;二者必须同时满足。

⑵方法重写的目的:子类通过方法重写可以隐藏继承的方法,可以把父类的状态和行为改变为自身的状态和行为。

●如果父类的方法被子类继承,子类有权重写方法,子类若重写了父类的方法,就隐藏了继承的方法,那么子类对象调用方法一定调用的是子类重写的方法。

●如果子类没有重写,而是继承了父类的方法,那么子类创建的对象可以调用父类的方法,只不过子类方法产生的行为和父类的相同而已。

class A {
    float computer(float x,float y) {
       return x+y;
    }
    public int g(int x,int y) {
       return x+y;
    }
}
class B extends A {
    float computer (float x,float y,double z) {  //方法的重载,不是重写,因为参数列表不一样
       return x-y;
    }
}
    public static void main(String args[]) {
      B b=new B();
      double result=b.computer(8,9);    //b调用重写的方法
      System.out.println(result);  
      int m=b.g(12,8);                 //b调用继承的方法
      System.out.println(m);      
    } 

⑶重写的注意事项:重写方法时,不允许降低方法的访问权限,但可以提高访问权限(访问权限从高到低的排列顺序:public、protected、友好的(一般默认不写)、private)。

class A{
       protected float f(float x,float y){
             return x-y;
    }
}
class B extend A{
           float f(float x,float y){        //非法,因为降低了访问权限
          return x+y;
    }
}
class C extends A{
         public float f(float x,float y){     //合法,提高了访问权限
              return x*y;
     }
}

五:super关键字:

❶用super操作被隐藏的成员变量和方法:

子类隐藏了继承的成员变量或方法,则子类创建的对象就不在拥有该变量或方法,该变量或方法就归关键字super所拥有。因此,如果在子类中想使用被子类隐藏的成员变量或方法,就需要使用关键字super。例如super.x、super.A()就是访问和调用被子类隐藏的成员变量x和方法 A()。

例如:

class Sum { 
    int n;
    float f() { 
       float sum=0;
       for(int i=1;i<=n;i++){    //1:循环变量初始化i=1;2判断循环条件i<=n
    	   sum=sum+i;
       }
         
       return sum;  
    }
}
class Average extends Sum {
    int n;  //100
    float f() { 
      float c;
      super.n=n;        //访问父类中被隐藏的属性n
      c=super.f();     //调用父类中被子类重写的方法f
      return c/n; 
    }
   float g() {
       float c;
       c=super.f();
       return c/2; 
   }
}
public class  {
   public static void main(String args[]) {
       Average aver=new Average();
       aver.n=100;
       float resultTwo=aver.g(); 
       float resultOne=aver.f();
       System.out.println("resultOne="+resultOne);
       System.out.println("resultTwo="+resultTwo);
   }
}

❷使用super调用父类的构造方法

如果子类的构造方法没有指明使用父类的那个构造方法,子类就调用父类不带参数的构造方法。

     由于子类不继承父类的构造方法,因此,子类在其构造方法中需使用super来调用父类的构造方法,而且super必须是子类构造方法中的头一条语句。

六:final关键字:finai关键字可以修饰类、成员变量和方法中的局部变量。

❶final类:可以使用final将类声明为final类。final类不能被继承,即不能有子类。

❷final方法:如果用final修饰父类中的一个方法,那么这个方法不允许被子类重写。

❸常量:如果成员变量或局部变量被修饰为final,那么他就是常量。由于常量在进行期间不允许再发生变化,所以常量在声明时没有默认值,要求程序在声明常量时指定常量的值。例如:

final class A {          //final类不能被继承
  final double PI=3.1415926;      // final修饰的变量就成为了常量,常量通常用大写,PI是常量
  public double getArea(final double r) {
     return PI*r*r;
  }
  public final void speak() {       //final修改的方法不能被子类重写
     System.out.println("您好,How's everything here ?");
  } 
}
public class {
   public static void main(String args[]) {
      A a=new A();
      System.out.println("面积:"+a.getArea(100));
      a.speak();     
   }
}

七:对象的上转型对象:

❶老虎虽是动物,但如果说老虎是动物时,就是去了老虎独有的属性和功能。假设Animal类是Tiger类的父类,当用子类创建一个对象。并把这个对象的引用放到父类的对象中时,

Animal a;
Tiger b=new tiger();
a=b;

称对象a是对象b的上转型对象。
上转型对象的特点:

❶上转型对象不能操作子类新增的成员变量,不能调用子类新增的成员方法;

❷上转型对象可以访问子类继承或隐藏的成员变量,也可以调用子类继承的方法或子类重写的实例方法。

八:继承与多态:

多态就是指父类的某个方法被其子类重写时,可以各自产生自己的功能行为。

例如下列展示多态的例子:

class  动物 {
   void cry() {
	   System.out.println("haha");
   }  
}
class 狗 extends 动物 {
   void cry() {
      System.out.println("汪汪....."); 
   }  
}
class 猫 extends 动物  {
   void cry() {
      System.out.println("喵喵....."); 
   }  
}
public class { 
   public static void main(String args[]) {
      动物 animal;
      animal = new 狗();
      animal.cry(); 
      animal=new 猫();
      animal.cry();
  }

九:abstract类和abstract方法

用关键字abstract修饰的类称为abstract类(抽象类)e.g

abstract class A{
       ...
  }

 用关键字abstract修饰的方法称为abstract方法(抽象类)e.g

abstract int min(int x,int y);

abstrat方法的规则:

❶只允许声明,没有方法体;

❷不允许使用final和abstract同时修饰一个方法或类;

❸不允许使用static修饰abstract方法(即abstract方法必须是实例方法)

十: 案例
群主发普通红包:
    
1. 群主的一笔金额,从群主余额中扣除,平均分成n等份,让成员领取。
2. 成员领取红包后,保存到成员余额中。

  请根据描述,完成案例中所有类的定义以及指定类之间的继承关系,并完成发红包的操作。

### Java子类继承的概念及用法 #### 一、继承的基本概念 在面向对象编程中,继承是一种重要的机制,允许一个类(称为子类或派生类)从另一个类(称为类或基类)继承属性和方法。通过这种方式,子类可以获得类的功能并可以对其进行扩展或修改。 Java继承使用 `extends` 关键字实现。以下是继承的核心特点: - **代码复用**:子类可以直接使用类已有的功能。 - **多态支持**:子类可以重写类的方法以提供不同的实现[^1]。 - **构造函数调用**:当创建子类的对象时,默认情况下会先调用类的无参构造函数完成初始化工作[^3]。 --- #### 二、继承的语法结构 下面展示了一个简单的继承例子: ```java // 定义类 public class Animal { String name; public Animal(String name) { this.name = name; } public void eat() { System.out.println(name + " is eating."); } } // 定义子类 public class Dog extends Animal { // 调用类构造器 public Dog(String name) { super(name); // 显式调用类构造器 } // 子类新增方法 public void bark() { System.out.println(name + " says woof!"); } // 方法重写 (Override) @Override public void eat() { System.out.println(name + " prefers dog food."); } } ``` 在这个例子中,`Dog` 类继承自 `Animal` 类,并且具有以下特性: - 自动获得了类中的字段 `name` 和方法 `eat()`。 - 可以定义自己的新方法 `bark()`。 - 提供了对类方法 `eat()` 的覆盖版本,从而改变了默认的行为[^2]。 --- #### 三、继承的关键知识点 ##### 1. 构造函数 `super` 如果子类需要显式调用类的带参数构造函数,则必须使用 `super(...)` 来指定如何传递参数给类构造器。如果没有显式的 `super` 或者 `this` 声明,在编译阶段会自动插入一条隐含语句 `super();`,这表示调用了类的无参构造函数[^4]。 示例代码如下: ```java class Parent { int value; Parent(int v) { value = v; } } class Child extends Parent { Child(int val) { super(val); // 必须存在此行才能正常运行 } } ``` ##### 2. 方法重写的规则 为了确保正确地重写了某个方法而不是意外地隐藏它,建议总是加上 `@Override` 注解。这样可以在不匹配签名的情况下由编译器发出警告。 例如: ```java @Override public void someMethod() {} ``` ##### 3. 访问控制符的影响 需要注意的是,只有那些访问权限允许被外部看到的方法才会真正参继承过程。比如私有 (`private`) 成员无法直接暴露给任何后代;而受保护 (`protected`) 则仅限于同一包内的其他类以及所有的子类可见。 --- #### 四、综合实例分析 考虑这样一个场景——设计一种交通工具体系结构,其中汽车作为具体的一种车辆类型应该具备基本行驶能力的同时还能表现出独特之处。 ```java // 抽象类 Vehicle abstract class Vehicle { protected String type; public Vehicle(String t){ this.type=t; } abstract void move(); void displayType(){ System.out.println("This vehicle's category:"+type); } } // 具体子类 Car 实现移动逻辑 class Car extends Vehicle{ private boolean hasTurboBoost=false; public Car(boolean turbo, String cat){ super(cat); setTurbo(turbo); } void setTurbo(boolean b){hasTurbo=b;} @Override void move(){ if(hasTurbo){ System.out.println("Car moves with Turbo Boost!!"); }else{ System.out.println("Standard car movement..."); } } } public class TestInheritance { public static void main(String []args){ Car mySportsCar=new Car(true,"Sedan"); mySportsCar.displayType();// 输出类别信息 mySportsCar.move(); // 展示运动方式 } } ``` 上述程序展示了完整的继承链路及其实际应用价值所在。 --- #### 总结 综上所述,Java 中的继承提供了强大的工具让开发者能够构建层次化的软件组件模型。合理运用这些技术可以帮助我们减少重复劳动量同时增强系统的灵活性可维护性。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值