面向对象类的继承,javascript面向对象继承实现

  面向对象类的继承,javascript面向对象继承实现

  

目录

继承什么是继承?子类访问父类的成员变量子类访问父类的不同成员变量子类访问父类的成员方法子类访问父类的不同方法子类访问父类的同名方法super关键字super访问父类的成员变量super访问父类的成员方法创建构造方法super和此差异顺序详细说明访问修改限定符继承方法和组合继承方法组合

 

  

继承

 

  00-1010继承是连接类与类的层次模型。它意味着一个类(称为子类和子接口)继承了另一个类(称为父类和父接口)的功能,并且可以增加自己新功能的能力。继承是类或接口之间最常见的关系。继承是一种关系。

  看完这些概念,你可能还是会疑惑。让我用简单的英语给你解释一下。我们也听说过现实生活中的传承,但也只是家族财产的传承,文明的传承,等等。那么,这些传承不就是把上一代传下来的东西都给了继承人吗?这些继承的东西,继承人可以随时使用,但继承人也有自己的东西。没错,这就是继承,我们写代码的时候把一些类的所有共性放在一起组成一个类(这个类就是父类),然后子类可以随时调用从父类继承的成员。这样就提取了所有的共性,实现了代码的重用。

  说了这么多,不写代码理解可能不是很透彻,我举个例子理解一下。

  实现狗:

  //实现一个dog类Dog { public String name//name public int age;//age公共字符串furColor//发色public void eat(){ system . out . println(this . name 吃饭!);} public void sleep(){ system . out . println(this . name sleep!);} public void bark(){ system . out . println(this . name Wang Wang );}}实现一个猫:

  //实现一个cat类Cat { public String name)//name public int age;//age公共字符串furColor//发色public void eat(){ system . out . println(this . name 吃饭!);} public void sleep(){ system . out . println(this . name sleep!);} public void mew(){ system . out . println(this . name 喵喵喵);}}我们都知道猫狗是动物。他们既有名字、年龄、吃饭睡觉等共同属性,也有狗会叫、猫会喵等各自属性。由于它们有共同的属性,我们可以创建一个动物类。

  //实现一个animal类class Animal { public String name//name public int age;//age公共字符串furColor//发色public void eat(){ system . out . println(this . name 吃饭!);} public void sleep(){ system . out . println(this . name sleep!);} }//实现一个狗类dog { public void bark(){ system . out . println( woof woof );} }//实现一个cat类cat { public void mew(){ system . out . println(喵喵喵);}}}既然我们把它们的共性都提取出来了,怎么用呢?

  显然不能直接用。需要怎么用?我们想要的是,狗和猫都应该具备这些属性,我们可以随时使用它们。我们接下来要讲的继承就很好的解决了这个问题。

  继承的语法:继承是指使用extends关键字来连接子类和父类。

  //实现dog类dog扩展animal { public void bark(){ system . out . prin

  tln(this.name+"汪汪汪"); }}//实现一个猫类class Cat extends Animal{ public void mew() { System.out.println("喵喵喵"); }}这回就不报错了。

  我们来分析一下这段代码:

  

 

  在这里子类又叫做派生类,父类可以叫做父类,基类还有超类。

  这里有一个问题:

  子类继承了父类的什么呢?

  答案是:除了构造方法所有。

  

 

  

子类访问父类的成员变量

 

  

子类访问父类非同名成员变量

//实现一个猫类class Cat extends Animal { public void mew() { System.out.println(this.name + "喵喵喵"); } public void Init() {//访问父类 this.name = "咪咪"; this.age = 2; this.furColor = "橘黄色"; } public void show() { System.out.println(name); System.out.println(age); System.out.println(furColor); }}

 

  这里就体现了继承的关系,子类继承了父类的属性(成员变量和成员方法);

  这里我们还可以调用构造方法初始化成员,调用toString方法来打印信息

  

//实现一个猫类class Cat extends Animal { public void mew() { System.out.println(this.name + "喵喵喵"); } public Cat(String name,int age,String furColor) { this.name =name; this.age=age; this.furColor =furColor; } @Override public String toString() { return "Cat{" + "name=" + name +  + ", age=" + age + ", furColor=" + furColor +  + }; }}public class TestDemo1 { public static void main(String[] args) { //Cat cat = new Cat(); Cat cat = new Cat("咪咪",2,"橘黄色"); cat.eat(); cat.sleep(); cat.mew(); System.out.println(cat.toString()); }}

 

  

 

  

子类访问父类同名成员变量

当子类成员变量名与父类成员变量同名了会怎么办呢???

 

  

//实现一个动物类class Animal{ public String name = "花花";//名字 public int age;//年龄 public String furColor;//毛颜色 public void eat() { System.out.println(this.name+"吃饭!!!"); } public void sleep() { System.out.println(this.name+"睡觉!!!"); }}//实现一个猫类class Cat extends Animal { public String name = "咪咪"; public void mew() { System.out.println(this.name + "喵喵喵"); } public void Init() {//访问父类 name = "咪咪"; this.age = 2; this.furColor = "橘黄色"; }}public class TestDemo1 { public static void main(String[] args) { Cat cat = new Cat(); System.out.println(cat.name); }}

 

  

 

  总结:当父类与子类同名时遵循就近原则,如果实例化子类对象就去子类找,找不到就去父类,父类没有就报错,如果实例化父类对象就直接去父类找,父类没有就报错。

  

 

  

子类访问父类的成员方法

 

  

子类访问父类的非同名方法

class Cat extends Animal { public String name = "咪咪"; public void mew() { System.out.println(this.name + "喵喵喵"); } public void methodSon() { System.out.println("我是子类的方法!!"); } public void method() { methodSon();//访问子类 methodFather();//访问父类 }}

 

  

子类访问父类的同名方法

//实现一个动物类class Animal{ public String name = "花花";//名字 public int age;//年龄 public String furColor;//毛颜色 public void method(int a) { System.out.println("我是父类的方法!!"+a); }}//实现一个猫类class Cat extends Animal { public String name = "咪咪"; public void mew() { System.out.println(this.name + "喵喵喵"); } public void method() { System.out.println("我是子类的方法!!"); }}public class TestDemo1 { public static void main(String[] args) { Cat cat = new Cat(); cat.method();//没有带参数的只有子类有,如果两者都有method同样的方法,那就涉及到重写(前提是引用子类对象)优先访问子类 cat.method(2);//带参数的只有父类有 //cat.method(); }}

子类访问父类同名的方法也是一样的也是采取就近原则,当引用子类对象的时候优先子类,然后去父类寻找,找不到报错。

 

  但是方法这里有两个特殊情况,一是方法重载,说明的是同一个类可以支持方法重载,不同类但是有继承关系的也是支持方法重载的。当出现方法重载,就会根据参数列表的不同来访问。

  二是方法重写,方法重写指的是方法名相同返回值相同,参数列表相同,当出现方法重写的时候(前提是引用子类对象)就优先子类,会出现动态绑定,这个咱后面讲解。

  上面我们都说同名的时候都会遵循就近原则。就比如我们引用子类对象的时候,我就想优先调用父类,那怎么办呢????

  那就该super关键字出场了;

  

 

  

super关键字

super就是一个普通的关键字,来引用当前对象的父类,当我们看见super的时候我们就要知道它是访问父类的就可以了。

 

  好我们来实践一下。

  

 

  

super访问父类成员变量

//实现一个动物类class Animal{ public String name = "花花";//名字 public int age;//年龄 public String furColor;//毛颜色}//实现一个猫类class Cat extends Animal { public String name = "咪咪"; public void mew() { System.out.println(this.name + "喵喵喵"); } public void method() { System.out.println(super.name); }}public class TestDemo1 { public static void main(String[] args) { Cat cat =new Cat(); cat.method(); }}

 

  

 

  

super访问父类成员方法

//实现一个动物类class Animal{ public String name = "花花";//名字 public int age;//年龄 public String furColor;//毛颜色 public void method() { System.out.println("我是父类的方法!!!"); }}//实现一个猫类class Cat extends Animal { public void method() { System.out.println("我是子类的方法"); } public void methodA() { super.method(); }}public class TestDemo1 { public static void main(String[] args) { Cat cat =new Cat(); cat.methodA(); }}

 

  

 

  

创建构造方法

 

  当我们为父类创建了一个构造方法并且为子类创建构造方法的时候就会报错,原因是什么呢???

  那就是当我们创建一个构造方法的时候一定要先为父类创建构造方法,原因是每个类都要至少要有一个构造方法,以前没有报错是因为编译器自动为我们生成了无参的构造方法。子类对象一般都有继承过来的属性还有自己独有的属性,在创建子类对象的时候,一般先执行父类的构造方法,将子类对象中继承父类的属性初始化完整,然后在调用自己的构造方法,为自己独有的属性初始化完整。

  所以我们一定要先为父类创建构造方法。

  怎么创建呢??? 与this一样只不过这是父类的构造方法,所以利用super关键字,利用super().

  

 

  同时super不能在静态方法中使用,并且当调用构造方法的时候this()和super()只能出现一个,并且出现在第一行。

  super要点:

  super关键字不能在静态方法中使用。super关键字只能放在方法中的第一行,并且与this()只能出现一个。super关键字访问父类属性 super.父类方法 super.父类成员变量 super()为父类提供构造方法。super关键字是引用父类的对象,当我们看见super的时候,他一定是引用父类的东西。当没有为父类写带有参数的构造方法的时候,编译器会为子类自动提供构造方法,当父类写了带有参数的构造方法,编译器不会为子类提供无参的构造方法,需要用户自己写,并且在写子类的构造方法的时候一定要先为父类构造。

 

  

super与this的区别

相同点:

 

  this与super关键均不能在静态方法中使用,静态方法不依赖于对象。并且只能放在方法的第一行。都是java中的关键字不同点:

  this是引用当前对象,super是用来引用当前对象的父类this()调用本类中的构造方法,super用来调用父类的构造方法。this调用非静态方法中本类当中的属性,super调用非静态方法中的父类的属性this是非静态方法中的隐藏参数,而super不是构造方法一定会有super的调用,当没有时候编译器会自动增加,而this不会同时增加一个this和super的内部图示:

  

 

  

 

  

顺序

静态代码块与实例代码块及构造方法的初始化顺序

 

  我们之前在上一篇文章讲解了初始化顺序,那时候还没有讲解继承思想,我们再来回忆一下,应该是静态代码块>实例代码块>构造方法,并且代码块只执行一次,也就是只保存一份,当我们构造了两个对象的时候,在实例化第一个对象会执行静态代码块,当实例化第二个代码块的时候,静态代码块不会执行。

  接下来我们与继承结合也就是有了父类和子类的静态代码块,构造方法,实例代码块。

  那他们的顺序又会是怎样的呢???

  我们来用代码实践一下,看结果到底是什么呢???

  

class Animal { public String name = "花花";//名字 public int age;//年龄 public String furColor;//毛颜色 static { System.out.println("我是父类的静态代码块!!!"); } { System.out.println("我是父类的实例化代码块!!!"); } public void eat() { System.out.println(this.name + "吃饭!!!"); } public void sleep() { System.out.println(this.name + "睡觉!!!"); } public void method() { System.out.println("我是父类的方法!!!"); } public Animal(String name, int age, String furColor) { this.name = name; this.age = age; this.furColor = furColor; System.out.println("我是父类的构造方法!!!"); }}//实现一个猫类class Cat extends Animal { public String name = "咪咪"; static { System.out.println("我是子类的静态代码块!!!"); } { System.out.println("我是子类的实例化代码块!!!"); } public Cat(String name, int age, String furColor) { super(name, age, furColor); System.out.println("我是子类的构造方法!!!"); } public void mew() { System.out.println(this.name + "喵喵喵"); } public void method() { System.out.println("我是子类的方法"); } public void methodA() { super.method(); } }public class TestDemo { public static void main(String[] args) { Cat cat = new Cat("咪咪",18,"橘黄色"); }}

这里还是用了上面的代码,定义了两个类,Animal类和子类Cat,我们同时定义了静态代码块实例代码块,构造方法。接下来运行一下看看顺序到底是什么呢???

 

  我们这里就可以总结一下了,还是静态代码块优先执行,只不过这里因为在构造子类时候优先构造父类所以是父类的静态的代码块优先于子类的静态代码块,然后是父类的实例和构造方法,最后是子类的实例和构造。

  还是一样的我们在创建一个对象看还会跟上次的结果一样么??

  

 

  总结:

  初始化顺序:父类静态代码块>子类静态代码块>父类实例代码块>父类构造方法>子类实例代码块>子类构造方法。如果是第二次实例化对象,那就没有静态代码块。

  这个应该很好记忆就是静态代码块优先然后实例代码块然后构造方法,因为构造子类之前要先构造父类所以父类的实例代码块和构造方法要大于子类的实例代码块和构造方法。

  

 

  

详解访问修饰限定符

访问修饰限定符public(公共的)private(私有的)protected(受保护的)default(默认权限)同一包的同一类yes√yes√yes√yes√同一包的不同类yes√No×yes√yes√不同包的子类yes√No×yes√No×不同报的非子类yes√No×No×No×看这个你可能会有些懵,接下来我会详细讲解。前提我们先要知道这些都是访问权限超过它自己的权限就不可以访问了。

 

  public:它是公共的意思是无论在哪里同一个包还是不同的包,同一类还是不同的类都可以进行访问。

  

 

  pivate :只能访问本类中的成员。

  

 

  default:默认权限就是成员前面啥也不加只能在同一个包中访问。

  这里注意:

  

 

  

 

  protected:可以在同一包中访问,可以再不同包中的子类访问,但是不可以在非子类访问,所以它与继承有很大的关系。

  

 

  总结访问修饰限定符:

  public 可以再同一包中的同一类不同类都能够访问,不同包的子类和非子类也能够访问。

  private 只能在本类中使用。

  default 也就是默认访问权限,什么也不加,只能在同一个包中访问。

  protected 可以在同一包中访问,也可以在不同包的子类访问。

  

 

  

继承方式与组合

 

  

继承方式

继承方式多种多样,如果能的话就可以一直继承下去,但在java中继承方式都有哪些呢???

 

  java中的继承方式可以进行单继承,多层继承。

  这里还有一个重要的点:那就是虽然可以继承很多,但是最少不要超过3成继承关系。那如果不小心多继承了呢?没关系我们可以利用final修饰,这样就可以停止继承了。

  

 

  但是java中不支持多继承也就是一个子类同时继承两个父类。

  

 

  这种是不可以的,如果java中要进行多继承的话那就出现了接口。

  

 

  

组合

如果要说组合的话,我们举个例子,组合嘛那就是一个东西由什么组成呗,比如汽车由发动机引擎,轮胎等等组成,学校由老师,学生,工作人员等等组成,而这些老师,学生,工作人员又有自己的属性。我们把这个学校就称为组合。

 

  那用代码如何表示呢??

  

class Teacher{//老师类 private String name; private int age;}class Student{//学生类 private String name; private int id;}class School{ //学校由学生和老师组成 private Student student[]; private Teacher teacher[];}

从这里我们也可以知道继承与组成本质到底是什么样的关系;

 

  我们把继承看做是一种 is a 关系:比如狗是一个动物,猫是一个动物

  我们把组合看做是一种 has a的关系:比如学校有 学生,老师,工作人员组成。

  那我们到底什么时候用组合,什么时候用继承呢???

  两种方式不一定就要用哪个。我们他们两的区别:1.继承是一种is....a的关系,我们都知道程序是先编译后运行,而继承关系就是在编译器编译截断下确定好的。组合关系是在运行时确定的。

  所以组合比继承更加简单灵活高效。我们如果非必要情况下优先选择组合。

  到此这篇关于Java全面分析面向对象之继承的文章就介绍到这了,更多相关Java继承内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: