继承是OOP一个重要特性。的主要目的就是代码的re-use,以减少代码量。并且可以很好的理解和管理class们。对java中的继承,了解下面这些要点就差不多了:
1. 继承的基本概念
2. is-a relationship
3. 关键词 extends
4. 构造函数和继承
5. 调用父类方法和变量: super
6. type-casting: upcasting 和 downcasting
7. instanceof
8. override和override的规则 **(hin重要)
9. inner class的继承
10. abstract class 和继承
11. 其他
继承是一个允许class继承另一个class的一些通用的fields和methods。几个概念:
要好好的理解继承,一定要牢牢的记住,is-a relationship。
子类 is-a 父类。
一只猫也是一只动物。
一个继承的例子:
//猫是动物,有动物的属性猫都有,所以Cat可以继承Animal
class Cat extends Animal{
private String color; //猫自己的属性。
//同时猫也继承了父亲的两个属性: vegetarian和noOfLegs。
//虽然在父类里是private的,并不能被子类access,但是还是会继承来。
public Cat(String color) {
//猫不是吃素的,有四条腿。
super(false,4); //调用了Animal里面第二个构造函数。
this.color=color;
}
//这类method叫setter和getter
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
public class Main
{
public static void main(String args[])
{
Cat cat = new Cat("black");
System.out.println("Cat color is " + cat.getColor());
//cat 可以调用父类里的方法。
//private的field只能通过getter来access
System.out.println("Cat is Vegetarian?" + cat.isVegetarian());
System.out.println("Cat has " + cat.getNoOfLegs() + " legs.");
}
}
输出:
an animal with 4 legs created
Cat is Vegetarian?false
Cat has 4 legs.
Cat color is black
super()
是子类用来调用父类构造函数的方法。 而且只能在子类的构造函数的第一行。 class Animal {
//如果添加一个带参数的constructor,那么Animal里面就没有default的constructor了
public Animal(boolean vegetarian, int legs){
System.out.println("an animal with " + legs + " legs created");
}
}
class Cat extends Animal{
//此时必须有构造函数,如果没有构造函数,那么系统会给一个默认的构造函数。
//默认的构造函数会调用父类默认的构造函数,然而Animal里面没有默认构造函数。
public Cat(String color) {
super(false,4); //这一行是必须的,否则会调用默认的构造函数。
this.color=color;
}
}
super
可以在子类里access父类的 非private 的field和method:class Animal {
private boolean vegetarian;
public int noOfLegs; //public的field
//....和上面的一样
public void setNoOfLegs(int noOfLegs) {
this.noOfLegs = noOfLegs;
}
}
class Cat extends Animal{
public Cat() {
super(false,4);
System.out.println(super.noOfLegs); //可以通过super访问父类的field
System.out.println(super.vegetarian);//这一行出错了,因为vegetarian是private
}
@Override //不要求写,但是如果写了,编译时就可以查出一些低级错误
public void setNoOfLegs(int noOfLegs){
super.setNoOfLegs(noOfLegs);//调用父亲的方法。
}
}
upcasting
。 这个过程是自动发生的。来个例子:Cat c = new Cat(); //c是一个Cat的实例(c是一只猫)。
Animal a = c; //也可以把c赋值给Animal类型的变量(c也是一个动物没毛病的)
Animal a2 = new Cat(); //等同于上面的写法。
downcasting
。如果把一个父类强制转化给一个错误的子类,那会抛出异常。来个例子:Animal a = new Cat(); // 虽然a是从Cat 创建的,但是被定义为Animal了。
a.getColor();//这行不合法,complie-time时的错误。
//因为getColor是Cat的方法,不是Animal的,而a被认为是动物。
Cat c1 = (Cat) a; //a是个动物,如果需要转换成Cat的实例,需要特别说明。
//这个可以成功,因为a是从c转换来的。a其实也是只猫
Animal a2 = new Dog();
Cat c2 = (Cat) a2; //runtime时抛出ClassCastException
//因为a2其实是只狗,没办法强制转成猫。
instanceof
是一个操作符。用来检测某个object是不是属于某一类。比较没节操,没啥限制。Cat c = new Cat();
Animal a = c; // 或者Animal a = new Cat();
boolean flag1 = c instanceof Cat; // true
boolean flag2 = c instanceof Animal; // true 因为 c 也是个 Animal
boolean flag3 = a instanceof Cat; //true 因为它的确也是一个猫。
子类里面可以override父类的方法。加上 @Override annotation 是很重要的。。。以防拼错写个新方法出来。override的规矩太多,以及面试经常考。
例子:
class Animal{
public void greeting() {
System.out.println("Hi, I am a Animal");
}
}
class Cat extends Animal {
@Override
public void greeting() {
System.out.println("Mome, I am a Cat");
}
}
public class Main {
public static void main(String args[]) {
Animal an = new Animal();
an.greeting(); //Hi, I am a Animal
Cat cat = new Cat();
cat.greeting(); //Mome, I am a Cat
//顺便看一下runtime 类型的意思 instanceof时提到的
Animal an2 = new Cat();
//虽然an2是个animal,但是被创建的时候是用Cat class,所以调用cat里的方法
an2.greeting();//Mome, I am a Cat
}
}
class OuterClass {
class InnerClassOne {
int x = 10;
void methodOfInnerClassOne() {
System.out.println("From InnerClassOne");
}
}
class InnerClassTwo extends InnerClassOne
{
//一个inner class继承另一个
}
}
public class InnerClasses {
public static void main(String args[]) {
OuterClass outer = new OuterClass(); //实例化outter class
OuterClass.InnerClassTwo innerTwo = outer.new InnerClassTwo(); //实例化 InnerClassTwo
System.out.println(innerTwo.x);
innerTwo.methodOfInnerClassOne();
}
}
class OuterClass {
static class InnerClassOne {}
class InnerClassTwo {}
}
class AnotherClassOne extends OuterClass.InnerClassOne {}
class AnotherClassTwo extends OuterClass.InnerClassTwo {
public AnotherClassTwo() {
new OuterClass().super();
}
}
class OuterClass {
int x;
void methodOfOuterClass() {
System.out.println("From OuterClass");
}
class InnerClass { //Class as a member
int y;
}
}
class AnotherClass extends OuterClass {
//只有field和method被继承了,如果要用inner class 的属性
//则需要有一个inner class继承父类的inner class
class AnotherInnerClass extends InnerClass {}
}
public class InnerClasses {
public static void main(String args[]) {
AnotherClass anotherClass = new AnotherClass(); //creating AnotherClass Object
System.out.println(anotherClass.x); //accessing inherited field x from OuterClass
anotherClass.methodOfOuterClass(); //calling inherited method from OuterClass
//Using the properties of InnerClass
AnotherClass.AnotherInnerClass anotherInnerClass = anotherClass.new AnotherInnerClass();
//creating object to AnotherInnerClass
System.out.println(anotherInnerClass.y); //accessing inherited field y from InnerClass
}
}
class OuterClass {
int x;
void methodOfOuterClass(){
System.out.println("From OuterClass");
}
class InnerClass extends OuterClass{ //Class as a member
//only fields and methods are inherited, but not member Inner Classes
}
class InnerClassOne{
//another class as a member
}
}
public class InnerClasses
{
public static void main(String args[])
{
OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = outer.new InnerClass(); //creating object to InnerClass
System.out.println(inner.x); //accesiing inherited field x
inner.methodOfOuterClass(); //accessing inherited method
}
}
代码来源: https://javaconceptoftheday.com/inheritance-inner-classes-java/
abstract class Base {
abstract void fun();
}
class Derived extends Base {
void fun() { System.out.println("Derived!"); }
}
class Main {
public static void main(String args[]) {
// Base b = new Base(); 这一行会引发编译错误。
//不能跟在new后面,但是可以作为reference。
Base b = new Derived();
b.fun(); //Derived!
}
}
abstract class Base {
Base() { System.out.println("Base Constructor Called"); }
abstract void fun();
}
class Derived extends Base {
Derived() { System.out.println("Derived Constructor Called"); }
}
class Main {
public static void main(String args[]) {
Derived d = new Derived();
}
}
Base Constructor Called
Derived Constructor Called
class Animal{
}
class Cat extends Animal {
}
Cat cat = new Cat();