面向对象——继承


面向对象

继承概述:

1、Java语言中,Java只支持单继承,不支持多继承。

即使一个类只能有一个子类(extends) 一个父类(super),不允许多个,容易有安全隐患。

(1)、比如,同时继承两个类,但是两个类中有连个同名函数。

(2)、但是Java保留了这种机制,并用另一种体现形式来完成表示,叫做多实现。

(3)、Java支持多层继承,也就是一个继承体系,B继承A,C继承B,这样C就既有了A的功能,又有了B的功能,这就是多继承。

2、使用一个继承体系的功能

(1)、要想使用体系,先查阅体系父类的描述,因为父类中,定义的是该体系中共性的功能。

(2)、通过了解共性功能,就可以知道该体系的基本功能。

(3)、那么这个体系已经可以基本使用了。

3、那么在具体调用时,要创建最子类的对象,还是父类对象?

(1)、有可能父类不能创建对象。

(2)、创建子类对象可以使用更多功能,包括基本的也包括子类特有的。

4、简单一句话:查阅父类功能,创建子类对象使用功能

继承的出现(Extends)

1,提高了代码的复用性。

2,让类与类之间产生了关系。有了这个关系,才有了多态的特性。

注意

千万不要为了获取其他类的功能,简化代码而继承。

必须是类与类之间有所属关系才可以继承,所属关系,父类、子类(is a)。

聚集关系:

类与类之间不只有继承关系,也有聚集(包括聚合和组合)关系。

1、聚合:球队由球员组成,球员是球队中的一个,球队中有球员。

2、组合:比聚合更紧密,心脏和身体的关系,不可分割。

子父类中变量的特点:

如果子类中出现非私有的同名成员变量时,子类要访问本类中的变量,用this

子类要访问父类中的同名变量,用super

super的使用和this的使用几乎一致,this代表的本类对象的引用,super代表的是父类对象的引用。

子父类中函数的特点:

当子类出现和父类一模一样的函数时,当子类对象调用该函数,会运行子类函数的内容,如同父类的函数被覆盖一样,这种情况是函数的另一个特性:重写(覆盖)。

当子类继承父类,沿袭了父类的功能到子类中,但是子类虽具备该功能,但是功能的内容却和父类不一致,这时,没有必要定义新功能,而是使用覆盖,保留父类的功能定义,并重写功能内容。

覆盖:子类覆盖父类,必须保证子类权限大于等于父类,才可以覆盖,否则编译失败。静态只能覆盖静态。

记住:重载只看同名函数的参数列表;重写子父类方法要一模一样。

子父类中构造函数的特点:

1)在对子类对象进行初始化时,父类的构造函数也会运行。

那是因为子类的构造函数默认第一行有一条隐式的语句super();

super():会访问父类中空参数的构造函数,而且子类中所有的构造函数默认第一行都是super();

2)子类一定要访问父类中的构造函数,因为父类中的数据子类可以直接获取,所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的,所以子类在对象初始化时 ,要先访问一下父类中的构造函数,如果要访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定。

注意:super语句一定要定义在子类构造函数的第一行。

继承弊端:打破了封装性。

子类的实例化过程:

结论: 子类的所有的构造函数,默认都会访问父类中空参数的构造函数。

因为子类每一个构造函数内的第一行都有一句隐式super();

当父类中没有空参数的构造函数时,子类必须手动通过super语句形式来指定要访问父类中的构造函数。

当然,子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。子类中至少会有一个构造函数会访问父类中的构造函数。

例如

class Super{

Super(){

//Super的父类又是谁呢?查阅API发现是Object,所以类都有一个父类就是Object。

super(){}

}

int num = 5;

public int show(){

return num;

}

}

class Extends extends Super{

Extends(){

super(){}

}

public String name;

Extends(String name){

this(){}

//等于Extends(){},如果定义了this(){}那么super(){}语句就不在了。

//而是在另外调用的构造函数里

this.name=name;

}

public int num = 10;

/*

子类的特有方法

*/

public int method(){

return super.num;

}

/*继承父类的方法

public int show(){

return num;

}

*/

}

class Test{

public static void main(String[] args){

//创建子类对象。

Extends zi =  new Extends();

//调用子类的method方法,获取父类的num值。

int methodnum = zi.method();

//为什么可以调用父类的show方法呢?因为子类继承了父类,所以就有了父类的方法。

int shownum = zi.show();

//打印结果为5,父类的变量。

System.out.println("methodnum="+methodnum);

//打印结果为10,子类的变量,因为子类有着和父类同样的成员变量,所以进行了覆盖。

System.out.println("shownum="+shownum);

//创建父类对象。

Super fu = new Super();

//这样调用是否可以?答案是不可以的,因为这是子类特有方法,父类无法访问。

//fu.method();

}

}

final——关键字最终值

1、可以修饰类、函数、变量。

2、被 final 修饰的类,不可以被继承,为了并避免被继承,被子类复写功能。

3、被 final修饰的方法。

4、被final修饰的变量是一个常量,只能赋值一次,既可以修饰成员变量,也可以修饰局部变量。

5、当在描述事物时,一些数据的出现 值是固定的,那么这时为了增强阅读性,都给这些值起个名字,方便于阅读,

而这个这不需要改变,所以加上final修饰。

6、比如 π值。

7、作为常量,敞亮的书写规范所有字母都大写,如果由多个单词组成,单词间通过 _ 连接。

8、一般是public static final 。。。这么使用。

9、内部类定义在类中的局部位置上时,只能访问该局部被 final修饰的局部变量。(等下会讲到,先有朦胧的概念)

抽象类——关键字:abstract 只能修饰类和方法

抽象:笼统,模糊,看不懂!不具体。

抽象类的概述:

当多个类中出现相同功能,但是功能主体不同,这时可以进行向上抽取。

这时,只抽取功能定义,而不抽取功能主体。

抽象类的特点(abstract)

1,方法只用声明没有实现时,该方法就是抽象方法,需要被abstract修饰。

       抽象方法必须定义在抽象类中。该类也必须被abstract修饰。

2,抽象类不可以被实例化(也就是创建对象的意思),为什么?因为调用抽象方法没意义。

3,抽象类必须有其子类覆盖了所有的抽象方法后,该子类才可以实例化。

否则, 这个子类还是抽象类。

问题:

1,抽象类中有构造函数吗?

       有,用于给子类进行初始化。

2,抽象类可不可以不定义抽象方法吗?

可以的。但是很少见,目的就是不让该类创建对象。AWT的适配器对象就是这种类。

通常这个类中的方法有方法体,但是却没有内容。

3,abstract关键字不可以和那些关键字共存?

private不行,抽象方法需要实现,私有,没办法实现覆盖原有方法。

static不行,静态的不用对象,直接类名调用,抽象方法没内容,没意义。

final不行,水火不容,抽象要被覆盖,但是final不能覆盖。

4,抽象类和一般类的异同点。

相同点:抽象类和一般类都是用来描述事物的,都在内部定义了成员。

不同点:

1,一般类有足够的信息描述事物。

抽象类描述事物的信息有可能不足。

2,一般类中不能定义抽象方法,只能定义非抽象方法。

抽象类中可定义抽象方法,同时也可以定义非抽象方法。

3,一般类可以被实例化。

抽象类不可以被实例化。

5,抽象类一定是父类吗?

是的。因为需要子类覆盖其方法后才可以对子类实例化。

抽象类练习:

/* 
雇员示例: 
需求:公司中程序员有姓名,工号,薪水,工作内容。 
项目经理除了有姓名,工号,薪水,还有奖金,工作内容。 
对给出需求进行数据建模。 
 
分析: 
在这个问题领域中,先找出涉及的对象。 
通过名词提炼法。 
程序员: 

属性:姓名,工号,薪水、 

行为:工作。 

经理: 

属性:姓名,工号,薪水,奖金。 

行为:工作。 


 
程序员和经理不存在着直接继承关系, 
 
但是程序员和经理却具有共性内容。 
可以进行抽取。因为他们都是公司的雇员  
 
可以将程序员和经理进行抽取.建立体系. 
*/  

  
//描述雇员。  
  

abstract class Employee  {  

private String name;  

private String id;  

private double pay;  

Employee(String name,String id,double pay){  

this.name = name;  

this.id = id;  

this.pay = pay;  

}  

public abstract void work();    

}  

//描述程序员。  
class Programmer extends Employee  {  

Programmer(String name,String id,double pay)  {  

super(name,id,pay);  

}  

public void work()  {  

System.out.println("code...");  

}  

}  
//描述经理。   
class Manager extends Employee  {  

private int bonus;  

Manager(String name,String id,double pay,int bonus)  {  

super(name,id,pay);  

this.bonus = bonus;  

}  

public void work()  {  

System.out.println("manage");  

}  

class Employee {

public static void main(String[] args){

Programmer programmer = new Programmer("黑马程序员——新长城","007",8000);

programmer.work();

Employee employee = new Employee("黑马程序员总经理","001",13000,2000);

employee.work();

}

}

模版方法设计模式

1、需求:获取一段程序运行的时间

2、原理:获取程序开始和结束的时间并相减

3、获取时间:System.currnetTimeMillis();

4、这种方式,叫模板方法设计模式

5、模板方法设计模式:在定义功能是,功能的一部分是确定的,但是有一部分是不确定的,而确定的部分在使用不确定的部分,那么这时就将不确定的那部分暴露出去,有该类的子类去完成。

例子:

abstract class GetTime{

public final void getTime(){

long start = System.currentTimeMillis();//暂时不需要理解,获取时间的而以

runCodeTime();

long end = System.currentTimeMillis();

System.out.println("毫秒:"+(end - start));

}

public abstract void runCodeTime();

}

class SubTime extends GetTime{

public void runCode(){

for(int x=0;x<4000;x++){

System.out.print(" "+x);

}

}

}

class Test{  

public static void main(String[] args){  

SubTime gt = new SubTime();

gt.getTime();

}

}

接口

当一个抽象类中的方法都是抽象的时候,这时可以将该抽象类用另一种形式定义和表示,就是接口 interface

格式: interface接口名{}

定义接口使用的关键字不是class,是interface

对于接口当中常见的成员:而且这些成员都有固定的修饰符。

1,全局常量。public static final 

2,抽象方法。public abstract

由此得出结义,接口中的成员都是公共的权限,都是public

 类与类之间是继承关系,类与接口之间是实现关系。

实现: implements


注意:接口不可以实例化。只能由实现了接口的子类并覆盖了接口中所有的抽象方法后,该子类才可以实例化。

否则这个子类也是抽象类。

在Java中不直接支持多继承,因为会出现调用的不确定性。

所以Java将多继承机制进行改良,在Java中变成了多实现。

一个类可以实现多个接口。

接口的出现将“多继承”通过另一种形式体现出来,即“多实现”。

接口的出现避免了单继承的局限性。

类与类是继承关系,类与接口是实现关系,接口与接口之间是继承关系,而且接口可以多继承。

 注意:接口的出现再次打破了单继承的局限。

接口的特点:

1,接口是对外暴露的规则。

2,接口是程序的功能扩展。

3,接口的出现降低耦合性。

4,接口可以用来多实现。

5,类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口。

6,接口与接口之间可以有继承关系。


接口与抽象类的异同点:

相同点:都是不断向上抽取而来的。

不同点:

1,抽象类需要被继承,而且只能单继承。接口需要被实现,而且可以多实现。

2,抽象类中可以定义抽象方法和非抽象方法,子类继承后,可以直接使用非抽象方法。

接口中只能定义抽象方法,必须由子类去实现。

3,抽象类的继承,是is a关系,在定义该体系的基本共性内容。接口的实现是like a关系。

interface Inter_1{
public static final int PI = 3.14;

public abstract void show();

}
interface Inter_2{

/*如果该类是接口的话,默认是权限修饰符是 public static final */ int PI = 4;

/*如果该类是接口的话,默认是权限修饰符是 public abstract */voidshow();

}

interface Inter_3 extends Inter_1{

public abstract void show();

}

class Demo implements Inter_1,Inter_2, Inter_3{

public static final int PI = 3.14;

public void show(){

System.out.println("Demo implements Inter_1");

}

}

class Test{  

public static void main(String[] args){  

Demo d = new Demo();

d.show();//"Demo implements Inter_1"

System.out.println(d.PI);

//最简单的调用接口类的方法,因为接口类的常量默认是静态的,所以可以类名.调用)

System.out.println(Demo.PI);

System.out.println(Inter_2.PI);

System.out.println(Inter_3.PI);//打印Inter_1的常量

}  

}

注意:接口的属性都是常量,而且是全局常量。接口中的方法都是抽象的。

(很重要)日后开发就是这种模式,一个项目大家分一点,一个人实现一个功能,就是这样机制。

接口的应用

/*

需求:数据库的操作。

数据是:用户信息。

1,连接数据库。JDBC  Hibernate

2,操作数据库。

c create r read  u update  d delete

3,关闭数据库连接。

*/

interface UserInfoDao{

public void add(User user);

public void delete(User user);

}

class UserInfoByJDBC implementsUserInofDao{

public void add(User user){

1,JDBC连接数据库。;

2,使用sql添加语句添加数据。;

3,关闭连接。

}

public void delete(User user){

1,JDBC连接数据库。;

2,使用sql添加语句删除数据。;

3,关闭连接。

}

}

class UserInfoByHibernate implements UserInfoDao{

public void add(User user){

1,Hibernate连接数据库。;

2,使用sql添加语句添加数据。;

3,关闭连接。

}

public void delete(User user){

1,Hibernate连接数据库。;

2,使用sql添加语句删除数据。;

3,关闭连接。

}

}

class  DBOperate{

public static void main(String[] args) {

//UserInfoByJDBC ui = new UserInfoByJDBC();

//UserInfoByHibernate ui = new UserInfoByHibernate();

//UserInfoDao ui = new UserInfoByHibernate();

UserInfoDao ui = new UserInfoByJDBC();

ui.add(user);

ui.delete(user);

}

}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值