黑马程序员_java面向对象(二) 继承,黑马_java
黑马程序员_java面向对象(二) 继承,黑马_java
------- android培训、java培训、java学习型技术博客期待与您交流! ----------
继承(Inherit)
1 概述
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类只要继承(extends)那个类即可。
继承的类为子类(派生类),被继承的类为父类(超类, 基类)。子类会自动继承父类所有的方法和属性。
作用:
当我们定义一个类时,发现另一个类的功能这个类都需要,而这个类又要增加一些新功能时,就可以使用extends
关键字继承那个类,这样那个被继承类的功能就都有了,不必重写编写代码。
只要在新类中编写新的功能即可,提高了代码的复用性。
继承的出现让类与类之间产生了关系,提供了多态的前提。
2 特点:
Java只支持单继承,不支持多继承,但是可以多重继承。如果一个类继承多个类,多个类中有相同的方法,子类调用
该方法时就不知道该调用哪一个类中的方法了。
一个类只能有一个父类,不可以有多个父类:
class SubDemo extends Demo{} //Yes
class SubDemo extends Demo1,Demo2... //No
java支持多层继承体系:
class A{}
class B extends A{}
class C extends B{}
注意:不要仅为了获取其它类中某个功能而去继承,类与类之间要有所属(" is a")关系,B是A的一种。
成员变量
如果子类中出现非私有的同名成员变量时,子类要访问本类中的变量,用this;访问父类中的同名变量 用super。
super的使用和this的使用几乎一致:
this代表的是本类对象的引用;super代表的是当前对象父类对象的引用。
成员函数
当子类出现和父类相同的函数时,子类对象调用该函数,会运行子类函数的内容。如同父类的函数被覆盖一样。
这种情况是函数的另一个特性: 重写(覆盖)(override)
子类对象实例化过程:
子类对象进行初始化时,父类的构造函数也会运行,因为子类的构造函数默认第一行有一条隐式的语句super()语句
它会访问父类中的空参数构造函数。而且子类中所有的构造函数默认第一行都是super(),在子类中第一行用this关
键字去调其它的构造方法,这时系统将不再自动调父类的。但其它构造函数中会调用父类构造函数。
继承细节:
在构造方法中this和super关键字只能出现一次,而且必须是第一个语句。
以后在设计类的时候,最好定义一个无参的构造方法,不然子类实例化的时候就容易出错。父类中没有空参构造
函数,子类的构造函数必须通过this或者super语句指定要访问的构造函数。
子类不继承父类私有成员:父类中私有成员对外不可见,子类对象中无法访问这些成员。
构造函数不被继承:构造函数通常用来初始化类的成员变量。而父类和子类的成员变量,初始化方式、构造函数的名
字都不相同。
向上转型:
子类对象可以当作父类对象使用,因为父类有的功能子类都有。反之不能,因为子类有的父类不一定有。
定义一个父类类型的变量来记住子类对象,这在程序中称之为向上转型,
强制类型转换:
把一个子类当做父类来用的时候,不能调用子类特有方法。因为编译时编译器会做语法检查,看到变量是父类类型
就会到父类中查找是否有该方法,没有则报错。这种情况下,就需要将父类类型强转成子类类型。以(子类名)
变量名形式进行强制类型转换
强制类型转换时,无论类型是否匹配编译都不会报错,但如果不匹配运行会报错,可以使用instanceof进行判断,
判断是否是该类型。
子类当做父类来用时,不能调用子类特有方法,如果一定要调用,就需要强制类型转换回子类。
在做转换时最好instanceof判断一下类型是否匹配。
3 函数覆盖(Override)
子类中出现与父类一模一样的方法时,会出现覆盖操作,也称为重写或者复写。
注意事项:
覆盖时,子类方法权限一定要大于等于父类方法权限;
静态只能覆盖静态:因为子类对象当做父类对象使用,父类对象中的方法在子类中必须都能获取到。
重写方法必须和被重写方法的方法名称、参数列表和返回值类型相同。子类方法返回值类型可以是父类方法返
回值类型的子类。
在子类覆盖方法中,继续使用被覆盖的方法可以通过super.函数名获取。如果直接调用方法,先在当前子类中查找,
如果子类有会调用子类的,使用super只在父类中查找,子类有没有都不调用;
重写方法时,不能比父类抛出更多的异常。子类只能比父类强,不能比父类弱。
父类中的私有方法不可以被覆盖。
重载(Overload)和重写(Override)的区别:
重载是方法名相同,参数列表不同,和返回值类型无关。
重写是方法名、参数列表、返回值类型全相同。
子类当做父类使用时需要注意:
当调用类的一个方法时,参数声明需要一个父类对象,可以将一个子类对象作为实参传递。此时方法的形参为父类,
在方法中使用父类变量调用方法时,其实是调用子类的方法。因为jvm会找到变量引用的地址,根据地址访问方法,
称为动态分配。这种机制没有被使用到类的成员变量上,如果用父类变量访问属性,会直接找父类的属性。
4 super关键字
super和this的用法相同:
this代表本类对象的引用
super代表父类的内存空间的标识。
当子父类出现同名成员时,可以用super进行区分
子类要调用父类构造函数时,可以使用super语句。
super和this的区别:
this :
代表对当前对象的引用
使用this关键字引用成员变量。
使用this关键字在自身构造方法内部引用其他构造方法。
使用this关键字代表自身类的对象。
使用this关键字引用成员方法
super:
代表当前对象里面的父类的内存空间的标识。
在子类的构造方法内部引用父类的构造方法。
在子类中调用父类中的成员方法。
在子类中调用父类中的成员变量。
5 final关键字
final可以修饰类,方法,变量。
final修饰的类不可以被继承。
final修饰的方法不可以被覆盖。
final修饰的变量是一个常量。只能被赋值一次。
内部类只能访问被final修饰的局部变量。
什么时候将变量修饰成final:
通常在程序中使用常见的一些不会变化的数据.也就是常量值.比如3.14,这个数直接使用是可以的,但并不利于阅读,
所以一般情况下,都会被该数据起个容易阅读的名称。
使用public static final共同修饰的常量就是全局常量。通常全部字母大写。double PI = 3.14;
如果由多个单词组成每个单词间用下划线连接;
final修饰变量赋值:
final修饰成员变量,必须初始化赋值,初始化有两种
final int NUM = 15; //显示初始化
NUM = 20; //错误,final修饰意味着不可以改变
final int NUM; //构造函数初始化,但是不能两个一起初始化
Demo() {
NUM = 15;
}
final和private小结:
final修饰的类可以访问
privateb不能修饰外部类,但可以修饰内部类,把外部类私有化是没有意义的
final修饰的方法不可以被子类重写
private修饰的方法不可以被子类重写的,子类看不到父类的私有方法
final修饰的变量只能在显示初始化或者构造函数初始化的时候赋值一次,以后不允许更改
private修饰的变量,也不允许直接被子类或包中的其它类访问或修改,但可以通过set和get方法进行访问
6 抽象类(abstract)
抽象定义:抽象就是从多个事物中将共性的,本质的内容抽取出来。
抽象类:Java中可以定义没有方法体的方法,该方法的具体实现由子类完成,该方法称为抽象方法。
包含抽象方法的类就是抽象类。
抽象方法的由来:多个对象都具备相同的功能,但是功能具体内容有所不同,那么在抽取过程中,只抽取了功能定义,
并未抽取功能主体。在功能声明,没有功能主体的方法称为抽象方法。
例如:狼和狗都有吼叫的方法,可吼叫内容是不一样的。所以抽象出来的犬科虽然有吼叫功能,但是
并不明确吼叫的细节。
抽象类特点:
抽象方法一定在抽象类中
抽象方法和抽象类都必须被abstract关键字修饰
抽象类不可以用new创建对象,因为抽象类本身是不具体的,没有对应的实例。调用抽象方法也没有没意义
抽象类中的抽象方法要被使用,必须由子类复写其所有的抽象方法后,建立子类对象调用;
如果子类只覆盖了部分的抽象方法,那么该子类还是抽象类。
抽象类中可以有抽象方法也可以有非抽象方法
抽象类和一般类没有太大的不同,该如何描述事物,就如何描述事物,只不过,该事物出现了一些看不懂得东西。
这些不确定的部分,也是该事物的功能,需要明确出现。但是无法定义主体
抽象类比一般类多了个抽象函数,就是在类中可以定义抽象方法; 抽象类不可以实例化。
特殊:抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象。
什么时候定义抽象类:
如果有多个类具有相同的方法声明,而方法的实现不一样,这时就可以抽象出父类,将方法在父类中声明;
在设计软件时,要尽力抽象父类,继承关系以3~4层为宜
抽象类中是否有构造函数?
只要是class定义的类里面就肯定有构造函数,抽象类中的函数是给子类实例化的;
抽象关键字abstract不可以和哪些关键字共存?
final:如果方法被抽象,就需要被覆盖,而final是不可以被覆盖,所以冲突。
private:如果函数被私有了,子类无法直接访问,不能覆盖
static : 不需要对象,类名即可以调用抽象方法。而调用抽象方法没有意义
7 模板设计模式(Template Pattern)
定义:定义功能时,功能的一部分是确定且不允许更改的,但是有一部分是不确定的,而确定的部分在使用不确定的部分,
那么这时就将不确定的部分暴露出去,由该类的子类去实现。这种方式称为模板设计模式。
为什么要使用模板方法设计模式:
在解决一些问题或者设计一个软件的时候,需要先定义一个模板,就相当于一种事先定义好的协议。
以后要做这系列的事情都按照这个模板来做。这样就实现统一化管理。
如何实现模板方法设计模式:
定义一个抽象的父类做为模板,定义所有需要的方法;
在父类中实现供外界调用的主方法,将方法声明为final;
根据不同业务需求定义子类实现父类的抽象方法;
class Demo {
public static void main(String[] args) {
SubTemplate st = new SubTemplate();//主函数建立子类对象,调用继承自父类的模板方法
st.method();
}
}
abstract class Template { //定义模板类,abstract修饰
public final void method() { //定义模板方法,final修饰
run(); //在模板方法中调用本类抽象方法
}
public abstract void run();
}
class SubTemplate extends Template { //子类extends模板类
public void run() { //复写抽象方法实现子类需要的功能
....
}
}
------- android培训、java培训、java学习型技术博客期待与您交流! ----------
相关文章
- 暂无相关文章
用户点评