java入门---面向对象编程之继承&构造器&内容补充说明

    接着上篇文章来,我们现在来看java继承中的构造器。子类不能继承父类的构造器(构造方法或者构造函数),但是父类的构造器带有参数的,则必须在子类的构造器中显式地通过super关键字调用父类的构造器并配以适当的参数列表。如果父类有无参构造器,则在子类的构造器中用super调用父类构造器不是必须的,如果没有使用super关键字,系统会自动调用父类的无参构造器:

class SuperClass {
  private int n;
  SuperClass(){
    System.out.println("SuperClass()");
  }
  SuperClass(int n) {
    System.out.println("SuperClass(int n)");
    this.n = n;
  }
}
class SubClass extends SuperClass{
  private int n;
 
  SubClass(){
    super(300);
    System.out.println("SubClass");
  }  
 
  public SubClass(int n){
    System.out.println("SubClass(int n):"+n);
    this.n = n;
  }
}
public class TestSuperSub{
  public static void main (String args[]){
    SubClass sc = new SubClass();
    SubClass sc2 = new SubClass(200);
  }
}

    运行结果为:

SuperClass(int n)
SubClass
SuperClass()
SubClass(int n):200

    然后我们来看其它的一些补充说明。首先java 中若要在子类调用父类的方法,需使用关键字super:

class Animal{
    void go(){
        System.out.println("animal go");
    }
}

class Dog extends Animal{
    void go(){
        //调用父类方法
        super.go();
    }
}

//驱动函数
public static void  main(String[] args){
    Dog dog=new Dog();
    dog.go();
}//输出animal go

    那么我们为什么使用继承呢?从已有的类派生出新的类,称为继承。在不同的类中也可能会有共同的特征和动作,可以把这些共同的特征和动作放在一个类中,让其它类共享。因此可以定义一个通用类,然后将其扩展为其它多个特定类,这些特定类继承通用类中的特征和动作。继承是 Java 中实现软件重用的重要手段,避免重复,易于维护,易于理解。

    再来看父类和子类。如果类 B 从类 A 派生,或者说类 B 扩展自类 A,或者说类 B 继承类 A,则称类 A 为"父类",也称为超类、基类,称类 B 为"子类",也称为次类、扩展类、派生类。子类从它的父类中继承可访问的数据域和方法,也可以添加新的数据域和新的方法。定义继承的语法如下:

修饰符 class 子类名 extends 父类名

    例如:Shape 类是父类,其子类可以有 Circle 类、Rectangle 类、Triangle 类,等等。关于继承我们需要注意如下几点:

  • 子类不是父类的子集,子类一般比父类包含更多的数据域和方法。
  • 父类中的 private 数据域在子类中是不可见的,因此在子类中不能直接使用它们。
  • 继承是为"是一个"的关系建模的,父类和其子类间必须存在"是一个"的关系,否则不能用继承。
    但也并不是所有"是一个"的关系都应该用继承。例如,正方形是一个矩形,但不能让 Square 类来继承 Rectangle 类,因为正方形不能从矩形扩展得到任何东西。正确的继承关系是 Square 类继承 Shape 类
  • Java 只允许单一继承(即一个子类只能有一个直接父类),C++ 可以多重继承(即一个子类有多个直接父类)。

    再来详细看下super关键字。super 表示使用它的类的父类。super 可用于如下方面:

  • 调用父类的构造方法;
  • 调用父类的方法(子类覆盖了父类的方法时);
  • 访问父类的数据域(可以这样用但没有必要这样用)。

    调用父类构造方法语法如下:

super();  

   

super(参数列表);

    不过要注意,super 语句必须是子类构造方法的第一条语句。不能在子类中使用父类构造方法名来调用父类构造方法。 父类的构造方法不被子类继承。调用父类的构造方法的唯一途径是使用 super 关键字,如果子类中没显式调用,则编译器自动将 super(); 作为子类构造方法的第一条语句。这会形成一个构造方法链。

    我们在静态方法中不能使用 super 关键字。调用父类方法语法如下:

super.方法名(参数列表);

    如果是继承的方法,是没有必要使用 super 来调用,直接即可调用。但如果子类覆盖或重写了父类的方法,则只有使用 super 才能在子类中调用父类中的被重写的方法。

    再来看下this关键字。this 关键字表示当前对象。可用于:

  • 调用当前类的构造方法,并且必须是方法的第一条语句。如:this(); 调用默认构造方法。this(参数); 调用带参构造方法。
  • 限定当前对象的数据域变量。一般用于方法内的局部变量与对象的数据域变量同名的情况。如 this.num = num。this.num 表示当前对象的数据域变量 num,而 num 表示方法中的局部变量。

    final 的作用随着所修饰的类型而不同。1、final 修饰类中的属性或者变量。无论属性是基本类型还是引用类型,final 所起的作用都是变量里面存放的"值"不能变。这个值,对于基本类型来说,变量里面放的就是实实在在的值,如 1,"abc" 等。而引用类型变量里面放的是个地址,所以用 final 修饰引用类型变量指的是它里面的地址不能变,并不是说这个地址所指向的对象或数组的内容不可以变,这个一定要注意。例如:类中有一个属性是 final Person p=new Person("name"); 那么你不能对 p 进行重新赋值,但是可以改变 p 里面属性的值 p.setName('newName');。final 修饰属性,声明变量时可以不赋值,而且一旦赋值就不能被修改了。对 final 属性可以在三个地方赋值:声明时、初始化块中、构造方法中,总之一定要赋值。2、final修饰类中的方法。作用:可以被继承,但继承后不能被重写。3、final修饰类。作用:类不可以被继承。

    java文件被编译成class文件时,在子类的所有构造函数中的第一行(第一个语句)会默认自动添加 super() 语句,在执行子类的构造函数前,总是会先执行父类中的构造函数。在编写代码要注意

  • 1.如果父类中不含 默认构造函数(就是 类名() ),那么子类中的super()语句就会执行失败,系统就会报错。一般 默认构造函数 编译时会自动添加,但如果类中已经有一个构造函数时,就不会添加。
  • 2.执行父类构造函数的语句只能放在函数内语句的首句,不然会报错。

    在继承关系中,在调用函数(方法)或者类中的成员变量时,JVM(JAVA虚拟机)会先检测当前的类(也就是子类)是否含有该函数或者成员变量,如果有,就执行子类中的,如果没有才会执行父类中的。如下:

public class Start
{
    public static void main(String[] args)
    {
        Cat cat=new Cat("Jack","黑色");
        cat.eat();
        cat.run();
        cat.sleep();
    }

}

class Animal 
{
    String name;
    
    public Animal(){}//必须要写这个构造函数,不然Cat类的代码会出错
    
    public Animal(String name)
    {
        this.name=name;
    }
    
    void eat()
    {
        System.out.println(name+"正在吃");
    }
    
    void run()
    {
        System.out.println(name+"正在奔跑");
    }
    
    void sleep()
    {
        System.out.println(name+"正在睡觉");
    }
}

class Cat extends Animal
{
    String color;
    public Cat(String name,String color)
    {
        this.name=name;
        this.color=color;
    }
    void eat()
    {
        System.out.println(color+"的"+name+"正在吃鱼");
        }
}

    运行结果为:

黑色的Jack正在吃鱼
Jack正在奔跑
Jack正在睡觉

    当子类出现与父类一样的函数时,这个被称为 重写 也叫 覆盖。Object类是所有类的直接父类或间接父类,也就是说是所有类的根父类,这个可以运用于参数的传递。如下:

public class Start
{
    public static void main(String[] args)
    {
        A a=new A();
        B b=new B();
        C c=new C();
        D d=new D();
        speak(a);
        speak(b);
        speak(c);
        speak(d);
    }
// instanceof 关键字是用于比较类与类是否相同,相同返回true,不同返回false
//当你不清楚你需要的参数是什么类型的,可以用Object来代替,Object可以代替任何类
    static void speak(Object obj)
    {
        if(obj instanceof A)//意思是:如果参数是 A 类,那么就执行一下语句
        {
            A aobj=(A)obj;//这里是向下转换,需要强制转换
            aobj.axx();
        }
        else if(obj instanceof B)
        {
            B bobj=(B)obj;
            bobj.bxx();
        }
        else if(obj instanceof C)
        {
            C cobj=(C)obj;
            cobj.cxx();
        }
    }
}
//这里举了四个类,他们的函数都不同,但都是 Object 类的子类
class A
{
    void axx()
    {
        System.out.println("Good morning!");
        System.out.println("This is A");
    }
}

class B
{
    void bxx()
    {
        System.out.println("Holle!");
        System.out.println("This is B");        
    }
}

class C
{
    void cxx()
    {
        System.out.println("Look!");
        System.out.println("This is C");        
    }
}

class D
{
    void dxx()
    {
        System.out.println("Oh!Bad!");
        System.out.println("This is D");        
    }
}

    运行结果为:

Good morning!
This is A
Holle!
This is B
Look!
This is C
    好啦,这次就到这里了。如果感觉不错的话,请多多点赞支持哦。。。

猜你喜欢

转载自blog.csdn.net/luyaran/article/details/80180445