Java面向对继概念(继承,子类持有了一个父类的引用super)

情形:

当类中有重复的属性或行为时,为了提高复用,类中只需要产生一种关系即可,关系:继承

方法:

找到他们的共性类型(无论是哪种职位,都是人,即可创建人这个类),将需要提供复用的代码进行抽取,定义到一个共性类中。

代码体现:

关键字:extends(继承)

如:

class Person

{

String name;

int age;

}

class Student extends Person

{}

Student 继承了Person,Student就是子类,Person就是父类(基类、超类)

好处:

提高代码的复用性,让类与类之间产生了关系,给另一个特征 多态 提供了前提

特点(在Java中):

允许单继承

不直接支持多继承,将多继承进行其他方式体现

单继承:

一个子类只能有一个父类

多继承:

一个子类可以有多个父类(Java优化了)

问题:父类中有相同的方法时,调用就会产生不确定性

Java中的解决办法:保留了多继承的好处,改良他的弊端,用多实现来体现

%多重继承(形成了继承体系):

如:B继承了A,C继承了B,那么C可以调用A 中的功能(先预览顶层(基本功能),创建底层(功能最多))

使用场景:

必须保证类与类之间有所属关系 。即 xxx是zzz的一种(学生是人的一种)。

继承出现后

重点体现:

1.成员变量(父类中私有的内容子类不可以直接访问)

特殊情况(这种情况一般不存在,因为父类一旦描述完了子类,子类直接使用就可以了):

子父类中定义了一模一样的成员变量,调用时,会访问本类中的成员变量,在程序运行时,先加载父类,再加载子类。创建子类对象时,该对象中有父类和子类两种成员变量(虽然是一样的),先super();访问父类,然后就显示初始化,之后子类显示初始化(各自的成员变量),访问时先找局部变量。

如果需要在子类中直接访问父类中的成员变量,只需要引用super,用法与this相似

this:本类对象的引用(直接输出没问题,可以输出类型和对应哈希值,但是super不行,因为没有创建父类的对象)

super:父类的内存空间

2.成员函数
特点:
特殊情况:

父类与子类定义了相同的方法时,运行子类的方法(函数的另一个特性override:覆盖、覆写、重写(API))

%重写

使用场景:修改源码可以解决问题,但是不利于后期的维护和扩展,父类已经定义了的功能,但是子类中内容不一致,可以保留原父类的方法 直接在子类中定义子类的内容即可,这就是重写!

如果子类重写还需要父类的功能可以调用父类中的方法,如:super.名称

//重写的注意事项:

1.子类覆盖父类,必须保证权限大于或等于父类的权限。

2.子类或者父类静态时,需要都为静态才可以覆盖

3.写法上一模一样,返回值类型、函数名、函数的参数列表相同

3.构造函数
子类实例化过程:

先执行父类的构造函数,再执行子的构造函数,因为子类所有构造函数中有一句隐式:super();默认调用的是父类中的空参数构造函数——子类会继承父类中的内容,所以子类在初始化时,必须先到父类中去执行父类的初始化动作,才可以更方便地使用父类中的内容

当父类中没有空参数构造函数时,子类的构造函数必须同构显示的super语句指定要访问的父类中的构造函数,而不建议使用在父类中创建空参数的父类构造函数(因为其没有空参数的构造函数说明其需要传值)。

细节(只要是构造函数必有隐式super(),Java体系在设计时,定义了所有对象的父类Object):

1.如果子类的构造函数第一行使用了this调用了本类其他构造函数,那么super调用父类语句就没有了,因为this()或super9(),只能定义在构造函数的第一行,因为初始化动作要先执行。(所以子类中必须有至少一个构造函数没有使用本类的其他构造函数)

2.父类构造函数中第一句任然是super();子间接继承Object。只要使用父类的初始化过程,只需要在子类构造函数中调用即可。

final(显示初始化的值,不能不显示初始化):

继承的弊端:

打破了封装性

可以通过final来实现

修饰符:

1.final是一个最终类,不能再派生子类

2.final可以修饰类、方法、变量(成员变量、局部变量、静态变量)

3.final修饰的变量常量时,只能被赋值一次(当程序中一个数据在使用时是固定不变的,可以给该数据起个名字,这就是变量,为了保证这个变量的值不被修改,加上final修饰,这就是一个阅读性很强的常量,书写规范,被final修饰的常量所有的字母都是大写的,如果由多个单词组成,单词间通过 _ 连接)

abstract(抽象):

情景:

当A类与B类中有共同的内容时,可以抽取所属共性内容,创建父类,但是,如果A类与B类,功能类似,但是表现不一样,可以在父类中定义一个函数

abstract name ();——抽象函数

定义了抽象函数的类也必须抽象化——抽象类(描述事物时,没有足够的信息描述一个事物时,这是该事物就是抽象事物)

抽象类的特点:

1.抽象类和抽象方法都要用abstract修饰,抽象方法一定要定义在抽象方法中

2.抽象类不可以创建实例,因为调用抽象方法没有意义

3.只有覆盖了抽象类中所有抽象方法后,子类才可以实例化,否则该子类依旧是一个抽象类

(之所以继承,更多的是在思想,面对共性类型操作会更简单)

细节:

1.抽象类一定是一父类,是不断抽取而来的

2.抽象类有构造函数,虽然不可以给自己的对象初始化,但是可以给自己的子类初始化

3.抽象类可以不定义抽象函数,意义仅仅是为了不让该类创建对象

4.abstract不能和final(final修饰的类不可能产生子类了,而抽象类必须有子类,所以冲突)、private(抽象函数在子类中要覆盖、重写,所以不能被私有化)、static(被static修饰可以通过类名调用,但是该方法为抽象函数,无意义)关键字共存

与一般类的异同:

相同:

1.他们都是用来描绘事物的

2.他们之中可以定义属性和行为

不同:

1.一般可以描绘具体的事物,抽象类描绘的事物信息不具体

2.抽象类中可以多定义一个成员:抽象函数

3.一般类可以创建对象,而抽象类不能创建对象

interface(接口):

情形:当一个抽象类里面方法全是抽象的,这是可以用接口来表示

定义:

interface Dema

{

abstract void show1;

abstract void show2;

}

1.定义变量:但是变量必须持有固定的修饰符,public static final,所以接口中的变量也称之为常量

2.定义方法:方法也有固定的修饰符,public abstract

其固定的修饰符可以不写,因为编译时会自动加上

特点:

1.接口不能创建对象

2.子类必须覆盖掉所有方法后,子类才可以实例化,否则子类是一个抽象类

接口继承的关键字(implements)

interface Dema

{

内容1;

内容2;

·

·

·

}

class DemoImpl implements Demo

{

//覆盖时方法必须要有关键字public,因为接口方法自带public,覆盖时没有会权限不够

}

重要体现

解决了多继承的弊端,将多继承这种机制在Java中实现了

当多继承时,多个父类中有相同功能时,子类会产生不确定性,核心原因是因为多继承的父类中功能有主体,而导致调用运行时,不确定运行哪个主体,接口中的功能没有方法体,由子类说了算,所以多实现解决了多继承的弊端。

可以增加类的功能:

interface Inter

{

public void 名称;

}

class Fu

{}

calss Zi extends Fu implements

{}

覆写之后的子类具有不同的形式,形成子类个性化,称为多态

//类与类中是继承关系,类与接口之间是实现关系,接口之间的关系是继承关系,而且可以多继承(接口与接口之间)

//抽象类中可以不定义抽象方法,原因是不让该类创建对象,如果某一个子类只需要用接口中的其中一种方法,可以将其他的方法用空方法覆盖,该类就不是抽象类,即可创建对象,但是如果有多个类,需要实现该接口中的其中一种或几种方法,那么代码的复用性会变差,于是可以创建一个实现类,实现类实现接口,并用空方法覆盖接口中的所有方法,于是新的需要实现接口的类可以直接继承实现类,此时,实现类已经把所有方法都覆盖了,那么就不需要进行重复的空方法覆盖了。

例:

//接口

interface Inter

{

public void show1();

public void show2();

public void show3();

public void show4();
}

//实现类

abstract class InterImp1 inplements Inter

{

//实现Inter接口中的所有方法

public void show1(){}

public void show2(){}

public void show3(){}

public void show4(){}

}

//子类1,如果需要使用show1,只需要让子类继承实现类即可

class InterImp11 extends Interlmp1

{

show1(){

内容;

}

}

//子类2,如果需要使用show4,只需要让子类继承实现类即可

class InterImp11 extends Interlmp1

{

show4(){

内容;

}

}

因为这个实现类此时创建对象没有意义,所以可以将这个类抽象化,即:没有抽象方法的抽象类

//不能将该类私有化(构造函数私有化也可以达到不能创建对象的目的),因为该类需要被其他类继承

接口的设计思想

  1. 接口的出现实现了扩展
  2. 接口的出现定义了规则
  3. 接口出现降低了耦合性

接口的出现,完成了解耦,说明两方,一方在使用这个规则,另一方在实现这个规则

接口和抽象类的区别

抽象类类负责描述事物的基本功能,可以定义非抽象方法,is a 关系

接口负责描述事物的扩展功能,只能定义抽象方法,负责功能扩展,is like关系

提高扩展性(多态)

将共性的功能抽取到父类中

创建对象时可以通过父类指向对象。

如:

Dog d = new Dog();

Cat c = new Cat();

Animal dd = new Dog();

Animal cc = new Cat();

体现:

父类或接口的引用指向自己的子类对象

弊端:

通过父类引用操作子类对象时,只能使用父类中已有的方法,不能操作子类特有的方法

多态的前提:
  1. 必须有关系:继承或实现
  2. 通常都有重写操作
向上转型:

父类型引用指向子类对象时,这就是对子类对象进行了类型的提升

提高程序的扩展性,不关系到子类型(子类型被隐蔽)

向下转型(多态情况下,子类方法的调用)

强制转换(ClassCastException 转换异常)

使用情形:当需要使用到子类对象的特有方法时

注意:

  • 无论是向上转型还是向上转型,最终都是子类对象做着类型的变化
  • 因为不明确具体子类对象类型,所以容易引发转换异常错误,为了避免这个错误,需要做类型的判断
  • 判断类型用的关键字,instanceof
    • 应用方法:a instance of b 意为判断a指向的对象类型是否为b类型,返回true或false
多态中,成员调用的特点:
  1. 成员变量

当子父类中出现同名的成员变量时,多态调用该变量时

编译时期:参考的是引用型变量所属的类是否有被调用的成员变量,没有则编译失败

运行时期:也是调用引用型变量所属的类中的成员变量

  1. 成员函数(对于成员函数是动态绑定到对象上)

当子父类中出现同名的方法时,多态调用该方法时

因为有重写存在,所以父类中的方法会被覆盖,所以会运行子类中的方法

当父类中没有该方法时,编译失败

  1. 静态函数(静态函数是不会被多态调用的,绑定于类中)

静态方法是存在于方法区的,静态方法和对象无关

Object类中的常用方法

Object类中定义了所有对象都具备的功能

查找方式:API(应用程序)文档

  1. equals 判断是否相同(地址),若子类需要判断则覆写其
  2. toString 转换成字符串(println()自动调用),建议子类都覆写该属性

内部类

定义及场景:

当A类中的内容要被B类直接访问,而A类还需要创建B的对象访问B的内容,此时可以将B类定义至A类的内部,这样访问更为便捷,将B类称为内部类(内置类、嵌套类),内部类必须有所属的,内部类可以直接访问外部类的所有成员包括私有变量,而外部列想访问内部类的成员必须先创建内部类对象。

内部类被访问的方式

情况一:内部类在成员位置上的被访问方式

成员是可以被指定的修饰符所修饰的(如:public,private,static)

public:

创建对象即可,但是此时该内部类为外部类的成员,所以先得有外部类的对象,才能有内部类的对象,即:

Outer.Inner in = new Outer().new Inner();

但是public对于并不常见于内部类,因为该类已经被封装到了外部类中,不直接对外提供

static:

内部类被静态关键字修饰后,因为内部类是静态,所以不需要创建外部类,可以直接创建内部类对象,即:

Outer.Inner in = new Outer.Inner();

//静态类中有静态成员的访问方式:静态内部类已经加载,直接通过类名调用即可,即:

Outer.Inner.方法();

//非静态内部类中不允许定义静态成员,仅允许在非静态内部类中定义静态常量 static final

//如果想在内部类中定义静态成员,那么这个内部类也要静态化

因为内部类持有了外部类的引用 外部类.this (静态类中没有,而是直接使用外部类名.)

情况二:内部类定义在外部类的局部变量中

局部内置类,不能被不能被成员修饰符修饰,内部类定义在局部时,只能调用局部变量中的最终(final)变量,因为该变量随着方法压栈和弹栈而生成和消失,所以不能访问局部变量

内部类的延伸

//看API,如果类名或者接口名中有.或$,说明该类为内部类

内部类是可以继承或实现其他类或接口的

可以改为父类对象创建对象并直接进行覆写,此时得到一个父类的子类对象,因为该类没有名字,为匿名内部类,就是内部类的简化形式,必须继承父类或者实现接口

局限:方法过多,不适合覆写

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值