黑马程序员----Java基础(六):面向对象之二

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

Java基础:面向对象

一、继承

1).定义:抽取一些类的共性内容,封装在一个类中,称为父类。一些类可以继承父类,通过继承原则,拥有父类中一切。

2).好处:
A.继承的出现,提高了代码的复用性;
B.继承的出现,让类与类之间产生关系,通过extends连接。

3).特点:
A.Java只支持单继承;
B.Java支持多层继承,形成一个继承体系(父类--子类--子子类).我们可以查阅父类功能,创建子类对象使用功能


二、子父类中的成员特点
1).成员变量:super() 引用

class Fu{
	int num=3;
}


class Zi extends Fu{
	int num =4;
	
	void show(){
	    //当局部变量和成员变量重名的时候用this来区分
		System.out.println("Zi num="+this.num);//this调用本类中的num
		System.out.println("Fu num="+super.num);//super调用父类中的num
	}
}

class ExtendsDemo2{
	public static void main(String[] args){
		
		Zi z = new Zi();
		z.show();
		
	}
}
/*
如果子类中出现非私有的同名变量时,
子类要访问本类中的变量时用this,
子类要访问父类中的变量时用super

 this代表本类对象的引用,谁调用本类,this就指向谁。
 super代表父类对象的引用。
 两者用法几乎一致。
*/

2).成员方法(函数)
class Fu1
{
	int num=3;
	void show()
	{
		System.out.println("fu show");
	}
}


class Zi2 extends Fu1
{

	void show()
	{
		System.out.println("zi show");
		System.out.println("子类中重写父类的show方法");	
	
	}
	
	/*int show(){          //不允许存在这种返回值类型不同的重写,因为本类继承了父类的方法,无法存在同名同参,不同返回值的函数。
		System.out.println();
		return 1;
		}	*/
}


class ExtendsDemo3
{
	public static void main(String[] args)
	{

		Zi2 z = new Zi2();
		z.show();
		
	}
}

/*
重写定义:
    当子类中出现和父类一模一样(函数名、参数列表、返回值)的函数时,
    当子类调用此函数时,会执行子类函数的内容,如同父类的函数被覆盖了一样,不会执行父类中的函数。
    这种情况是函数的另一种特性:重写(覆盖)

重写意义:
    当子类继承了父类,子类发现父类的方法体不再适用时,可以将父类的这个方法,保留方法名,修改方法体。
    此时,父类的方法就得到了拓展,子类可以有自己的独特方法。
    

 注意事项:
    1、子类覆盖父类,必须保证子类权限大于或等于父类权限,才可以覆盖,否则编译失败。
    2、静态只能覆盖静态,不能覆盖非静态。
    3、父类中被重写的方法,不能私有化,否则也不算重写。只能算是子类的新定义。
    

    补充:权限大小:public >  protected  >  private 
*/



3).子父类中的构造(方法)函数
class Fu3
{
	
	int num ;
	
	Fu3()
	{
		num = 90;
		System.out.println("Fu run");
	}
	
	Fu3(int x)
	{
		System.out.println("Fu run 有参构造");
	}
	
}

class Zi3 extends Fu3
{
	
	Zi3()
	{
		//super();
		//super(3); 当父类中没有空参构造函数,只有有参的构造函数时,必须手动定义有参函数。
		System.out.println("Zi run 空参构造");
	}
	
	Zi3(int x)
	{
		//super(); 	有参构造函数中也有super();
		//super(3);  当父类中没有空参构造函数,只有有参的构造函数时,必须手动定义有参函数。
		System.out.println("zi run 有参构造");
	}
	
}


class ExtendsDemo4
{
	public static void main(String[] args)
	{
		
		Zi3 z = new Zi3();
		    /*运行结果:
		        Fu run + num90
		        Zi run
		        可知:此语句第一运行了隐藏的super().输出了父类空参构造函数的语句
		        第二运行了子类中的空参构造函数
		    */
		new Zi3(3);
		 /*运行结果:
		        Fu run + num90
                Zi run 有参构造
		        可知:此语句第一运行了隐藏的super().输出了父类空参构造函数的语句
		        第二运行了子类中的有参构造函数。
		    */
	}
}
/*
3:子父类中的构造函数
 
 在对子类对象进行初始化时,父类的构造函数也会运行。
 
 原因:
    子类构造函数默认第一行有一条隐式的语句是:super();
    super();会访问父类中的空参构造函数,
    并且子类中所有构造函数默认第一行都是super();
    
    
 注意:
    子类的实例化过程:
        总结:
                当父类中没有空参数构造函数,子类必须手动通过super或者this语句来形式来指定要访问父类中的构造函数
                当然,子类的构造函数第一行手动指定this语句来访问本类中的构造函数。
                子类中至少会有一个构造函数会访问父类中的构造函数
 
 应用:
 class person{
 	private String name;
 	person(name){
 		this.name = name;
 	}
 	void show(){
 	}
 }
 
 class student extends person{
 	student(String name){
 		super(name);   //将name值赋给父类中的有参构造函数,完成name赋值。无需自己动手,直接交给父类完成。
 	}
 	void method(){
 		super.show();
 	}
 	
 }
*/




三、final修饰符
final  最终。
1、作为一个修饰符,可以修饰类、函数、变量。
2、被final修饰的类,不能继承;(为了避免被继承,防止子类复习功能)
3、被final修饰的方法,不能被复写;
4、被final修饰的常量,只能赋值一次。既可以修饰成员变量,也可以修饰局部变量;
当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都给这些值起个名字,方便阅读。
而这个值不需要改变,所以加上final修饰。
常量的书写规范:所有字母都要大写。由多个单词组成,单词间通过下划线 _ 连接
public static final double MY_PI = 3.14;



权限最大,可通过类名直接调用,无法被赋值,全局变量

5、内部类定义在类中的局部位置撒上时,只能访问该局部被final修饰的局部变量。

四、抽象类

abstract  

用处:当多个类中出现相同功能,但是功能主体不同时,也可以向上抽取。
这时,我们只抽取功能定义,不抽取功能主体。

抽象类的特点:
1、抽象方法一定存放于抽象类中
2、抽象方法和抽象类都必须被abstract关键字修饰
3、抽象类不可用new创建对象,因为调用抽象方法没有意义
4、抽象类中的抽象方法要被使用,必须由子类复写其所有抽象方法后,建立子类对象调用。
如果子类只覆盖部分抽象方法,该子类还是一个抽象类。
abstract class study{
	
	//void study(){system.out.println("study");}; 
	//由于BaseStudent和AdvStudent都重写了父类study的方法,但是由于各自功能主体的不同,继承这个方法多余。
	//所以,我们这样做:
	
	abstract void study(); //抽象方法,必须存放在抽象类中,于是class前必须添加abstract
	
	abstract void study1();  //如果此抽象类中还有抽象方法,子类中必须将这个方法也覆盖一次,否则报错。
	
	void sleep(){       //非抽象方法无须强制覆盖
		System.out.println("躺着");
	}
}

class BaseStudent extends study {
	void study(){
		System.out.println("base study");
	}
	
	void stude1(){
	    system.out.println("BaseStudent子类,抽象父类中的抽象方法必须被重写");
	}
}


class AdvStudent extends study {
	void study(){
		System.out.println("adv study");
	}
	void stude1(){
	    system.out.println("AdvStudent子类,抽象父类中的抽象方法必须被重写");
	}
	
}


class AbstractDemo{
	public static void mian(String[] args){
		
		//new study();  //报错,因为父类是抽象类,无法创建对象
		BaseStudent base = new BaseStudent();
		base.study();
	}

}

注意:
抽象类的相关问题:

A:抽象关键字abstract不可以和哪些关键字共存?
|--private
私有的,外部直接无法访问。子类也同样无法访问
|--abstrac修饰的方法就是为了让子类继承并重写的

|--static
那么这个时候抽象方法就可以可以通过类名调用,但是这样是没有意义的。
因为抽象方法中没有方法体,没有语句用于执行

|--final
final修饰的方法不能被重写。所以它和abstract冲突。
B:抽象类中可不可以没有抽象方法?
可以。如果这么做只有一个目的不让你创建这个类的对象


抽象练习
/*抽象练习
 
 假如我们开发一个系统时,需要对员工进行建模。员工包括3个属性: 姓名,工号,工资。
经理也是员工,除了含有员工的属性外,另外还有一个奖金的属性。
请使用继承的思想设计出员工类和经理类。
要求类中提供必要的方法进行属性访问。
 
 思想:
 首先创建一个员工类作为抽象父类,其中定义有三个属性为姓名、工号、工资,以及一个工作方式的抽象方法
 然后定义经理类,其中定义一个独有的奖金属性,使用自身的构造函数赋值。
 在定义一个普通员工类。
 
 
 */
 
 //定义抽象父类,Employee员工累
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;
    }
    
    //定义抽象方法
    abstract void work();
}

//定义经理类,继承父类Employee
class Manage extends Employee{
    //定义经理类的奖金属性
    private int bonus;
    
    //使用子类构造函数,为属性赋值
    Manage(String name, String id, double pay, int bonus){
        super(name,id,pay);     //由于父类中已有三个属性的赋值方法,直接使用super语句为其赋值
        this.bonus = bonus;
    }
    public void work(){
        System.out.println("经理工作");
    }
}

class Pro extends Employee{
    Pro(String name, String id, double bonus){
        super(name,id,bonus);
    }
    public void work(){
        System.out.println("普通员工");
    }
}

class AbstractTest1{
    public static void main(String[] args){
        Manage m = new Manage("huangwu","20100909",9000,1000);
        m.work();
        
        Pro p = new Pro("lisi","20130202",3500);
        p.work();
    }
}







模版方法模式
package extendsDemo;
/*
模版方法模式

需求;获取一段程序运行的时间
原理:获取程序开始和结束的时间,并相减

获取时间:System.currentTimeMillis();

当代码完成后,就可以解决这一类相同的问题。
这种方法就是:模版方法设计模式

什么是模版方法设计?
在定义功能时,功能的一部分是确定的,有一部分是不确定的。而确定的部分在使用不确定的部分。
那么此时就将不确定的部分暴露出去,由该类的子类来完成。

*/
abstract class GetTime{
	
	public final void getTime(){                   //不是一定要添加final,视具体情况而定
		long star = System.currentTimeMillis();
		
		runcode();
		
		long end = System.currentTimeMillis();
		
		System.out.println("毫秒:" + (end - star));
	}
	
	public abstract void runcode();			//不是一定要添加abstract,视具体情况而定。
}

class subTime extends GetTime{
	
	public void runcode(){
		for(int x=0; x<101; x++){
			System.out.print(x);
		}
	}
	
}



class AbstractTest2{
	public static void main(String[] args){
		
//		getTime gt = new getTime();
//		gt.getTime();
		
		subTime  st = new subTime();
		st.getTime();
	}
}


五、接口interface()
定义: 当一个类中的所有方法都是抽象类时,就无需定义abstract类,可以定义interface类

成员特点:
A)只有成员变量和成员方法
B)成员都有默认修饰符
成员变量:默认修饰符 public static final(可以省略不写)
成员函数:默认修饰符 public abstract(可以省略不写)

接口java中只能单继承的问题,让多继承以另一种优化方式存在
A)类与类:只能是单继承(extends)
B)接口与接口:可以单继承,可以多继承(extends)
C)类与接口:可以是单实现,可以是多实现(implements)
interface A{
}
interface B{
}
class C implements A,b{
}


接口的特点:

A)接口是对外暴露的原则
B)接口是程序的拓展
C)接口可以实现多实现
D)类与接口的实现关系,而且类可以继承一个类的同时,实现多个接口
E)接口与接口之间可以有继承关系

接口类与抽象类的区别:

A)抽象类只能被单继承(extends),接口类可以被多实现(employee)
B)成员的不同:
抽象类:成员变量可抽象,可不抽象;成员方法可抽象,可不抽象;构造方法可以用以实例化
接口类:成员变量有默认修饰符 public static final;成员方法有默认修饰符 public abstract

C) 抽象类中定义的是继承体系中的共性内容;
接口类中定义的是对象的扩展功能。

接口实例:


//接口实例

abstract class Stu{
	abstract void study();
	public void slepp(){
		System.out.println("休息时间");
	}
}

interface smoking{
	public void smoke();
}

class zhansan extends Stu implements smoking{ //zhansan学员即学习也吸烟,所以先继承类,在实现吸烟
	public void study(){
		System.out.println("高三");
	}
	public void smoke(){
		System.out.println("吸烟");
	}
}
class limei extends Stu{					 //limei学员只学习不吸烟,所以只继承类,不实现吸烟
	public void study(){
		System.out.println("高三");
	}
}
//总结:继承类用来得到共性的内容,实现接口为了拓展其他内容,达到功能拓展的目地,由后期子类去实例化



class interfaceTest1{
	public static void main(String[] args){
		zhangsan zs = new zhangsan();
		zs.sytudy();
		zs.smoke();
		
		limei lm = new limei();
		lm.study();
	}
	
}








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值