您的位置:首页 > 编程语言 > Java开发

java 面向对象三大特性之一:继承

2018-03-15 00:15 369 查看
      前言:
   继承,既是对现有类的复用。如果子类继承了父类,那么子类就拥有了父类的能力了。除此之外,子类还能加入自己新加入的方法,功能,或是重新定义从父类继承的某项功能。这样,就可以在现有的功能上开发新的功能,这样能大大减少开发的周期.

|继承的优点|

 现在我们来构建一个Cat的类package Test.practice.thinking_in_java.extend_test;

/**
* @Author 7aY
* @Description: TODO()
* @Date :Create in 13:202018/3/12
*/

/**
* 猫类
*/
public class Cat {
private int age;//年龄
private int weigth;//体重
private String name;//名字

public int getAge() {
return age;
}
public Cat(int age,int weigth,String name){
this.age=age;
this.weigth=weigth;
this.name=name;

}

public void setAge(int age) {
this.age = age;
}

public int getWeigth() {
return weigth;
}

public void setWeigth(int weigth) {
this.weigth = weigth;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
public void printMessage(){
System.out.println("name:"+getName()+" weigth:"+getWeigth()+"kg age:"+getAge());
}
public Cat(){}

}
这个Cat类包含体重 名字 身高等信息,但现在我想要在这个Cat的基础上创建一个EgyptianCat的类,我要重新把之前的代码重新再写一次然后再添加新的东西下去吗?很显然这会十分的麻烦且无用,所以这时候extend 这个关键字发挥了他的用处了public class EgyptianCat extends Cat {
private String color;

public String getColor() {
return color;
}

public void setColor(String color) {
this.color = color;
}
public EgyptianCat(int height,int weigth,String name,String color){
super(height,weigth,name);
this.color=color;
}

@Override
public void printMessage() {

System.out.println("name:"+getName()+" weigth:"+getWeigth()+"kg age:"+getAge()+"color:"+getColor());
}
}和Cat相比,EgyptianCat就多了个一个私用属性color,通过extend继承,我们的类构建可以简洁很多,并且可以在继承的基础上重新构建一个属于我们新类的方法,这种方法叫做重写方法(PS:重写方法会调用上一层继承的被重写方法)

这里我们重写了父类的printMessage()方法,在打印信息中新加入了color属性
现在我们来new下父类和子类并且调用他们的printMessage方法查看下结果 public static void main(String[] args) {
Cat cat = new Cat(2,10,"jay");
cat.printMessage();
EgyptianCat egyptianCat = new EgyptianCat(3,5,"lois","black");
egyptianCat.printMessage();

}输出结果为:name:jay weigth:10kg age:2
name:lois weigth:5kg age:3 color:black

|成员的继承|

如果子类继承了父类,则:
1.子类继承父类的所有public与protect成员,无论子类是否与父类在同一个包中;
2.如果子类与父类在同一个包中,那么子类也会继承父类包访问权限
3.子类不能继承父类的私有成员,但是子类可以通过父类的public或protect方法间接访问父类的私有成员package Test.practice.thinking_in_java.extend_test;

/**
* @Author 7aY
* @Description: TODO()
* @Date :Create in 22:212018/3/13
*/
public class SuperClass {
public int public_value;
protected int protect_value;
private int private_value;
public SuperClass(){
public_value=1;
protect_value=2;
}

public int getPrivate_value() {
return private_value;
}

public void setPrivate_value(int private_value) {
this.private_value = private_value;
}
}在SuperClass这个类中我们声明三种访问权限的变量,让我们看下他的子类是怎么继承成员变量的package Test.practice.thinking_in_java.extend_test;

/**
* @Author 7aY
* @Description: TODO()
* @Date :Create in 22:242018/3/13
*/
public class ExtendClass extends SuperClass {

public void printMessage() {
System.out.println("public value:"+public_value);
System.out.println("protect value"+protect_value);
// System.out.println("private value"+private_value); 并不能直接访问私有属性
System.out.println("private value:"+getPrivate_value());
}

public static void main(String[] args) {
ExtendClass extendClass = new ExtendClass();
extendClass.setPrivate_value(3);
extendClass.printMessage();

}
}我们新创建了一个ExtendClass类,其中声明了一个printMessage打印出成员变量的信息,让我们看下结果吧public value:1
protect value2
private value:3结果说明,子类能直接继承父类的public和protect成员变量,但并不能直接继承私有变量,但能通过setter和getter方法来访问private变量

|继承的向上转型和向下转型|

如果子类继承了父类,那么我们可以认为子类是父类的其中一种,是父类的特殊拓展版,例如Cat类继承于Animal类,那么我们可以把Cat看做为Animal,Cat具有Animal的所有特征,但并不能把Animal看做为Cat,因为并不是所有的Animal都是Cat.
 在Java中,我们可以把父类的引用赋值给子类的对象,然后通过父类的引用来进行操作,这种操作被称为向上转型,但是,子类的新增方法并不能进行使用和操作。我们不能把子类的引用赋值给父类的对象,就像前面所说的,可以把Cat看做为Animal,Cat具有Animal的所有特征,但并不能把Animal看做为Cat,因为并不是所有的Animal都是Cat.package Test.practice.thinking_in_java.extend_test;

/**
* @Author 7aY
* @Description: TODO()
* @Date :Create in 22:432018/3/13
*/
public class Animal {
public void walk(){
System.out.println("Animal walk!!");
}
public void sleep(){
System.out.println("Animal sleep!!");
}
public void eat(){
System.out.println("Animal eat!!");
}
}我们现在创建一个Animal类,然后我们再创建一个Cat类继承于Animal类package Test.practice.thinking_in_java.extend_test;

/**
* @Author 7aY
* @Description: TODO()
* @Date :Create in 13:202018/3/12
*/

/**
* 猫类
*/
public class Cat extends Animal {
private int age;//年龄
private int weigth;//体重
private String name;//名字

public int getAge() {
return age;
}
public Cat(int age,int weigth,String name){
this.age=age;
this.weigth=weigth;
this.name=name;

}

public void setAge(int age) {
this.age = age;
}

public int getWeigth() {
return weigth;
}

public void setWeigth(int weigth) {
this.weigth = weigth;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
public void printMessage(){
System.out.println("name:"+getName()+" weigth:"+getWeigth()+"kg age:"+getAge());
}
public Cat(){}
public void Meow(){
System.out.println("meow!!!!");
}
}其中Cat类中新增了一个Meow的猫叫方法
现在我们来测试一下:package Test.practice.thinking_in_java.extend_test;

/**
* @Author 7aY
* @Description: TODO()
* @Date :Create in 22:492018/3/13
*/
public class Test {
public static void main(String[] args) {
Animal cat = new Cat();
cat.eat();
cat.sleep();
cat.walk();
//但是不能调用Meow这个方法,现在我们把cat引用转为Cat
cat=(Cat) cat;
((Cat) cat).Meow();
//Cat animal = new Animal(); 编译器报错,并不能向下转型!

}
}
结果:Animal eat!!
Animal sleep!!
Animal walk!!
meow!!!!正如之前所说的一样,父类引用指向子类对象不能使用子类自己新增的方法,而且如果向下转型的话编译器会报错,那么向下转型有什么作用呢?之后我们会提到.

|多态的实现|

 现在我们要编写一个动物园类,检查传入的动物是什么动物package Test.practice.thinking_in_java.extend_test;

/**
* @Author 7aY
* @Description: TODO()
* @Date :Create in 0:212018/3/15
*/
public class Zoo {
//动物园检查动物
public void check(Animal animal){
System.out.println("this is animal!");

}
public void check(Cat cat){
System.out.println("this is cat!");

}
public void check(EgyptianCat egyptianCat){
System.out.println("this is egyptianCat!");

}

public static void main(String[] args) {
Zoo zoo = new Zoo();
Animal animal = new Animal();
Cat cat = new Cat();
EgyptianCat egyptianCat = new EgyptianCat();
zoo.check(animal);
zoo.check(cat);
zoo.check(egyptianCat);
}
}
结果:this is animal!
this is cat!
this is egyptianCat!以上的代码是check方法的重载,看上去没有任何问题.但只要我们稍加修改,用到上面的向上转型,结果则会出人意料 public static void main(String[] args) {
Zoo zoo = new Zoo();
Animal animal = new Animal();
Cat cat = new Cat();
Animal egyptianCat = new EgyptianCat();
zoo.check(animal);
zoo.check(cat);
zoo.check(egyptianCat);
}
}输出结果:this is animal!
this is cat!
this is animal!这是因为方法重载是静态的,传入参数类型是看类型的引用,前面cat的引用类型是Animal,所有编译器自动把cat传到Animal的重载方法中。
现在我们稍加修改public class Zoo {
//动物园检查动物

public void check(Animal animal){
animal.printInfo();
}

public static void main(String[] args) {
Zoo zoo = new Zoo();
Animal animal = new Animal();
Cat cat = new Cat();
Animal egyptianCat = new EgyptianCat();
zoo.check(animal);
zoo.check(cat);
zoo.check(egyptianCat);
}
}结果为:this is Animal
this is cat
this is EgyptianCat
这里说明一下,Animal 、Cat、EgyptianCat类中都有一个printInfo方法打印出自身的信息
从结果可以看出,虽然是向上转型,但是仍能准确输出类的信息,并且在Zoo类中并不需要重载方法,试想一下每当有一个新的类出现就重载一次,那么这个Zoo类的重载方法是不是太多了,以后管理起来也不方便,但使用多态的话,这需要在子类中重写方法即可,十分的方便。

【总结】

 使用继承这个关键字extend 能减少我们代码编写的工作量,但在重写的时候要注意,例如重写,类的变量继承等
因为有了继承,使得代码的复用有了千变万化的机会




                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: