写在前面:这几天仍然课程很多,正在积极学习恢复更新,这里的类与对象会多分享几个小节
学习内容安排
JAVA基础课程学习:数据类型(一)、运算符表达式和程序结构控制(二)、面向对象基础:类与对象和接口(三)、面向对象基础:继承抽象多态封装(四)、异常类和常用实用类(五)、组件和事件处理(六)、IO和JDBC(七)、泛型和集合函数(八)。
四、面向对象基础:继承抽象多态封装
前面我们分享了如何来定义类,以及类和变量的相关概念,今天主要来分享一下继承、子类与对象、方法重写、super、final、对象的上转型对象、abstract、接口。首先我们来讲一下继承。
继承
所谓继承就是子辈继承父辈的一些东西,也就是子类继承父类的一些属性或者方法,然后子类还可以增加自己的一些属性或者方法,我们使用extend来进行子类与父类的继承,
//这里定义了一个F1父类,有height、weight、money,然后父亲可以挣钱和唱歌
package tt;
class F2 {
public int height;
float weight; //友好的不再同一个包就不行了
private float money = 100;
void sing(){
System.out.println("song");
}
}
//下面来定义一个子类
//子类有全新的书信id,还可以学习
class SS extends F2 {
String id;
SS(){
}
void study(){
}
public static void main(String[] args) {
SS ss = new SS();
ss.height = 180;
//先调用父类的构造函数在调用自己的构造函数
ss.sing();//自动调用不带参数的父类的构造方法方法
ss.study();
}
}
对于子类可以对父类的变量进行赋值更改,还可以调用父类的方法,比如这里调用了父类的sing和自己类的study函数,于是输出的是,
song
子类与对象
子类创建对象时,子类的构造方法总是先调用父类的某个构造方法,完成父类部分的创建,然后再调用子类自己的构造方法,完成子类部分的创建。如果子类的构造方法没有明确的指向父类的哪个构造方法,那么就调用父类的不带参数的构造方法。如果父类的构造方法都带参数那么就必须输入参数,可以利用super进行调用,但在子类的构造函数中第一句就必须是super。
对于子类只能操作被继承的成员变量,而没有去权限继承的变量,则可以使用调用父类方法,来进行使用。
package tt;
class F2 {
public int height;
float weight; //友好的不再同一个包就不行了
private float money = 100;
F2(int x){
System.out.println(x);
}
void getMoney(){
System.out.println(money);
}
void sing(){
System.out.println("song");
}
}
//下面来定义一个子类
//子类有全新的书信id,还可以学习
class SS extends F2 {
String id;
SS(int y){
super(y); //super调用父辈构造方法
}
void study(){
}
public static void main(String[] args) {
SS ss = new SS(5); // 调用带参数的构造函数
ss.height = 180;
ss.sing();
ss.study();
ss.getMoney(); //调用含不可使用的变量的方法
}
}
于是可以得到输出结果应该是返回了5的父辈构造函数,sing方法里的song已经getMoney里的money值。
5
song
100.0
这里值得注意的是子类不能继承父类的构造方法,但是可以使用super进行调用。
方法重写
所谓方法重写就是,原本在父类里存在的方法,可以在子类里进行重新设置,然后输出。如果子类重写了父类的方法,那么在子类中调用该方法时默认使用重写后的方法。重写的时候需要注意的是,不能降低方法的访问权限,但是可以提高,
package tt;
//定义父类
class driveC1 {
private void passRule(int A, int B, int C){
int total = A + B + C;
if(total >= 60){
System.out.println("通过了C1驾驶考试");
}else{
System.out.println("没有通过C1哦");
}
}
}
//定义子类
class driveA1 extends driveC1{
public void passRule(int A, int B, int C){//加大了子类的权限
int total = A + B + C;
if(total >= 90){
System.out.println("通过了A1驾驶考试");
}else{
System.out.println("没有通过A1哦");
}
}
}
public class Csdn3_2_2{
public static void main(String[] args) {
int A = 50, B = 20, C = 10;
driveA1 driver = new driveA1();//调用子类
driver.passRule(A, B, C);//调用重写方法
}
}
根据上面说的,调用重写的反复默认为子类重写后的方法,所以输出结果应该是没有通过A1哦,
没有通过A1哦
super、final关键字
下面来讲一下super和final关键字,suoer关键字是用来操作被隐藏的成员变量和方法的,如果子类想调用父类中隐藏的成员变量与方法的话就可以使用super.x、super.play(),进行调用。还有super可以来调用构造函数,在前面已经涉及。
对于final关键字其实就是用来终止继承的延续性,也就是该类不能再有子类的生成,final可以对于类别也可以对于方法和变量,
package tt;
//生成父类
class Sum {
int n;
float f(){
float sum = 0;
for(int i = 1; i < n; i++){
sum += i;
}
return sum;// 定义一个求和的函数
}
}
//生成子类
final class Ave extends Sum{
int n = 6;
Ave(){
double x = f();
System.out.println(x); //子类的构造函数
}
float f(){
float c;
super.n = 5; //调用父类的n
c = super.f();//调用父类的f,类似于this
return c/n;
}//重写f函数
public static void main(String[] args) {
Ave ave =new Ave();
}
}
从上面的程序我们可以看到,我们首先使用了子类的n=6与父类的n=5,也使用了子类的f()求平均方法,也调用了父类的f()求和方法,于是我们得到输出值为,
1.6666666269302368
对象的上转型对象
这个名字看上去比较复杂,当然读上去也比较复杂,其实理解起来还是不那么复杂的,我们举个例子,我们有父类并且声明了a,还有子类声明了b,当我们令a = b时,相当于就是将b从子类升级成为了父类中的变量,会获得父类中的隐藏变量,但同时会失去一些能力,此时就称a为对象的上转型对象,
具体的能力如下,
能力名称 | 对象类型 |
---|---|
隐藏的变量 | 对象的上转型对象 |
继承的变量 | 对象的上转型对象、普通对象 |
新增的变量 | 普通对象 |
继承或重写的方法 | 对象的上转型对象、普通对象 |
新增的方法 | 普通对象 |
从这张表可以看出,对象的上转型对象不能够使用新增变量以及新增方法,
package tt;
public class Csdn3_2_4 {
public static void main(String[] args) {
Father man;
Child child = new Child();
man = child;//设置上转型变量
man.speak("Yes, I am a man"); //继承的方法
Child son = (Child) man;//将满转化为Child类
son.learn(10);//新方法
}
}
//设置父类
class Father{
void speak(String s){
System.out.println(s);
}
}
//设置子类
class Child extends Father{
void learn(int a){
int c = 2 * a;
System.out.println(c);
}//新方法
void speak(String s){
System.out.println("******"+s);
}//重写的方法
}
我们可以通过上述程序看到,我们的父亲有说话的能力,但孩子只能呀呀呀的说话,但孩子有新的学习的能力,如果我们将孩子中的一个变量赋值给父类中的变量,那么以为着上转型变量将无法学习,但能够说话,因为这里存在重写,所以还是孩子一样的说话。然后可以通过将上转型变量强制变为孩子一类,才能够使用learn()方法,
******Yes, I am a man
20
abstract
下面我们来讲一下abstract类和abstract方法,所谓abstract其实就是创建抽象类与抽象方法,其作用就是暂时只是声明有这么个类或者方法存在,但不去实现它,一般就作为架构师的角度,将各种功能先进行布局,然后让下面的人进行完成,
package tt;
//设置父类抽象类,意味着类中包含抽象方法
abstract class Test {
void read(){
}//已有的read方法
abstract void add();//抽象的求和add方法
abstract void sum(int x); //抽象的求和方法,这些都需要下面的人来完成
}
//设置子类1,这个子类就必须完成父类的抽象方法工作,或者继续继承给下一个人完成
abstract class Test2 extends Test{
void sum(int x){//完成sum()方法
}//必须要来实现,部分完成,让下面的在来完成add()
}
//最后设置子类来完成最后的add方法
class Test3 extends Test2{
void add(){
}
}
接口
在接口之前我们提一个开闭原则,这是一种程序设计的思想,开也就是系统对扩展开放,闭也就是对修改关闭。这样的做法就能够保证再设计后产生许多不必要的修改。
好了,我们来简单的说一下接口。为了克服JAVA单继承的缺点,JAVA使用了接口,也就是一个类可以实现多个接口,接口的特点,
1.由interface关键词修饰的称之为接口;
2.接口中可以定义成员变量,但是这些成员变量默认都是public static final的常量。
3.接口中没有已经实现的方法,全部是抽象方法。
4.一个类实现某一接口,必须实现接口中定义的所有方法。
5.一个类可以实现多个接口。继承与接口的区别
总之接口就是一个更加抽象的概念,下面我们来说明一下接口在日常生活中的使用示意图,一个项目有三级,负责人、小组长和员工,一般负责人利用interface写好接口,也就是构造好需要的内容框架,然后分发给下面的小组长完成,小组长则针对接口构造抽象类,或者完成方法,然后再给员工完成具体实现。
我们用一个小的实例来展示一下接口,interface声明接口,implement链接接口
package tt;
public interface Csdn3_2_6 { //创建接口
void sum();
int add(int x, int y);
}
abstract class NewClass implements Csdn3_2_6{
public void sum(){//因为接口的时候是public所以需要在前面加上public
}//将剩下的add交给下面的完成
}
class NewClass1 extends NewClass{//完成add类
public int add(int x, int y){
return x + y;
}
}
结语
以上就是本节的全部内容,主要涉及的就是继承方面的相关东西。
今天的更新,将接口的简单内容加在了最后。
谢谢阅读。