黑马程序员--- 学习笔记(第七天)

 —————————— ASP.Net+Android+IOS开发.Net培训、期待与您交流!——————————
继承 
   必须是类与类之间有所属关系,所属关系是:is a (谁是谁中的一员)


   比如有学生和工人两个类
   将学生和工人的共性部分提取出来,单独描述,只要让学生和工人与

   单独描述的这个类有关系就可以了.


/*
继承测试类
*/
class Demo1 
{
	public static void main(String[] args) 
	{
		new Student("学生",15).study();
		new Worker("工人",20).work();
	}

}
/*人类*/
class Person
{
	private String name;
	private int   age;
	public void setName(String name){
		this.name=name;
	}
	public String getName(){
		 return name;
	}
	public void setAge(int age){
		this.age=age;
	}
	public int getAge(){
		return age;
	}
	public Person(String name,int age){
		this.name=name;
		this.age=age;
	}
}
/*学生 继承 人类*/
class Student extends Person
{
	public Student(String name, int age){
		super(name,age); //调用父类的构造方法
	}
	/*学生特有的行为*/
	public void study(){
	   System.out.println(getName()+"学习");
	}
}
/*工人 继承  人类 */
class Worker  extends Person
{
	public Worker(String name, int age){
		super(name, age); //调用父类的构造方法
	}
	/*工人特有行为*/
	public void work(){
	  System.out.println(getName()+"工作");
	}
}




   利:
1.提高代码的复用性
2.让类与类之间产生了关系,有了这关系,才有多态的特性
   弊:
1.打破了封装性


注意:千万别单纯为了获取其他类的功能简化代码而继承


java中只支持单继承,不支持多继承,因为多继承带来安全隐患,假如情况如下:
当父类中都定义了相当的功能,当功能内容却不同,子类对象不确定要运行哪一个


但是java保留了这种机制,并用另一种体现形式来完成表达,多实现(interface)


java支持多层继承


如何使用一个继承体系的功能?
想要使用体系,先查阅体系父类中描述,因为父类中定义的是体系中的共性功能,
通过了解共性功能,就可以知道该体系的基本功能,那这个体系已经可以基本使用了.


那么在具体调用的时候,要创建最子类的对象,为什么呢?
1.是因为有可能父类不能创建对象
2.创建子类对象可以使用更多的功能,包括基本也包括特有的.


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


聚集:所属关系:has a (谁里面有谁)
    集合:例如一个学校,有很多的学生组成(可有可无的)
    组合:例如一个有很多的器官组成(必须的)
   
 子类继承父类后类成员的特点:
类中成员:
1.变量
2.函数
3.构造函数


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


super的使用this基本一致
this代表本类对象的引用
super代表父类对象的引用


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


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

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


记住:
1.重载:只看同名函数的参数个数,参数类型,与返回值无关
2.重写:父类与子类的函数一模一样,包括返回值


3.构造函数
在对子类进行初始化时,父类的构造函数也会运行,会先于子类构造函数
那是因为子类构造函数有一条隐式的super(),会访问父类中空参数的构造函数
而且子类中所有的构造函数默认第一行都是super();


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


注意:super语句一定只能定义在子类构造函数第一行


结论:子类的所有构造函数默认都会访问父类中的空参数的构造函数,因为
每一个子类构造函数第一行都一条一句隐式的super();
当然父类的构造函数也可以手动指定this来访问本类中构造函数,子类中也
至少会有一个构造函数访问父类中的构造函数.


java中的上帝:超类 object


为什么this和super不能同在一行?
因为他们都只能在第一行
为什么必须在第一行?
因为初始化一定要先做


/*
继承后变量, 函数 ,构造函数 的特点  同名
*/
class Demo2 
{
	public static void main(String[] args) 
	{
		 new Zi(50).show();
		 new Zi(50).method();
	}
}
class Fu
{	 
	private int num;
	public void setNum(int num){
	   this.num=num;
	}
	public int getNum(){
		return num;
	}
	public Fu(){
	
	}

	public Fu(int num){
		this.num=num;
	}
	public void method(){
		System.out.println("fu...");
	}
}
class Zi extends Fu
{
   private int num;	 //父类有的共性,之类不应在有,这是测试 

	public Zi(){
		//一条隐式的父类构造函数
	}
	public Zi(int num){
		//手动指定父类的构造函数
	//调用父类的初始化构造函数	子类至少有一个父类的构造函数
		super(num);
	}

	public int getNum(){
		return num;
	}

   /*输出num*/
   public void show(){
	   //也是调用父类的getNum 获取父类的num	
	   //子类重写getNum  才是调用子类的num
		System.out.println(getNum());
		//需要调用父类的,用super关键字	这才是父类的 
		System.out.println(super.getNum());
   }


   /*与父类的同名时 权限等于或大于父类才能覆盖 输出子类的*/
   /*当父类的成员为 private 不存在重写 因为不被继承*/
    public void method(){
	System.out.println("zi...");
	}
}


final关键字


final:最终的 作为一个修饰符
1.可以修饰类,函数,变量
2.被final修饰的类不可以被继承,为了避免被继承,被子类重写功能
3.被final修饰的方法不可以被重写
4.被final修饰的变量是一个常量,只能赋值一次,既可以修饰成员变量也可以修饰局部变量
5.内部类定义在类类中的局部位置上只能访问被final修饰的局部变量



  当描述事物时,一些数据的出现值时固定的那么这时为了增强阅读性,
  都给这些值起名字,方便与阅读,而这个值不需要改变,所以加上final修饰,
  常量所有字母均大写,多单词用_连接


写代码,阅读性很重要.


/*
final 关键字
*/
class Demo3 
{
	//final static 一起用就是共享的固定的数值 例如PI 全部字母大写 
	//多单词用下_连接
	final static double PI=3.14; 
			
	public static void main(String[] args) 
	{

		PI=30;			//final修饰的变量也是不可修改的
	}
}
/*
//final 用于类
final class A  
{
}

class B extends A //错误的	 被final修饰的类无法继承
{

}
*/

 
 //final 用于函数
class F
{
	public final void method(){
	 //static int d=10;  函数不能定义static	
	 //final int d=10;	   函数内可以定义final
	 System.out.println("fu");
	}
} /*
class Z extends F
{
	public void method(){ //无法覆盖父类的method,父类的被final修饰了
	System.out.println("zi");
	}
}
*/


private不能修饰类


抽象类(abstract class)
当多个类出现相同的功能,但是功能主体不同,这是可以进行向上抽取,
只抽取功能而不抽取功能主体.这时候就可以使用抽象类来描述.


 抽象:看不懂   关键字:abstract


 抽象类的特点:
 1.抽象方法必须定义在抽象类中
 2.抽象方法和抽象类都必须使用abstract关键字修饰
 3.抽象类不可以用new创建对象,因为创建没意思
 4.抽象类的抽象方法被使用,必须有子类复写所有的抽象方法,建立
 子类对象使用.如果子类只覆盖了部分,那么该子类就是一个抽象类

/*
抽象类测试
*/
class Demo4 
{
	public static void main(String[] args) 
	{
		//new Test1(); //抽象类不能实例化(new)
		new Test2(88).method();
	}
}
/*
//错误  抽象方法只能在抽象类里
class Test1
{
  public abstract void method(); 
}
 */
 /*
 抽象类与其他类描述一样 可以有成员,构造函数 只是多了不确定的部分
 */
abstract  class Test1
{
	private int num;
	public void setNum(int num){
		this.num=num;
	}
	public int getNum(){
		return num;
	}
	public Test1(){
	
	}
	public Test1(int num){
		this.num=num;
	}
  public abstract void method(); 
  public void show(){
	System.out.println("absctract ");
  }
}
/*子类要全部重写父类的抽象方法,否则子类就是抽象类 不能实例化*/
class Test2 extends Test1
{
	  public Test2(int num){
	  	super(num);
	  }
	/*重写父类的method*/
	public void method(){
		System.out.println(getNum());
	}
}



 抽象类和普通的类没啥区别,该如何描述事物就如何描述事物,只不过
 事物出现了一些看不懂的东西,不确定的功能定义,但还是需要明确出现
 ,只是无方法体而已..


 抽象类既可以由抽象方法和非抽象方法,抽象方法只能定义在 抽象类中
 抽象可以没有抽象方法,这样做仅仅是让该类建立对象而已.


 /*
 需求:
 假如我们开发一个系统时需要对员工进行建模,员工包括了3个属性:
 姓名,工号,以及工资,经理也是员工,除了员工的属性外还有一个特有
 的提成属性,请使用继承思想设计,需求:类中提供公开的方法进行对外访问
 */
/*
需求: 开发一个系统,对员工进行建模,员工有三个属性:姓名,年龄,工资
经理也是员工,除了特点的属性还有一个提成属性, 请用继承思想实现
对外提供访问属性方法
*/
class Demo5 
{
	public static void main(String[] args) 
	{
		new Worker("张三",15,2222).work();
		new Manager("李四",15,1111111,11).work();
	}
}
abstract class Employee
{
	private String name;
	private int age;
	private double salary;
	public void setName(String name){
		this.name=name;
	}
	public String getName(){
		return name;
	}
	public void setAge(int age){
		 this.age=age;
	}
	public int getAge(){
		 return age;
	}
	public void setSalary(double salary){
		 this.salary=salary;
	}
	public double getSalary(){
		return salary;
	}
	public Employee(String name, int age, double salary){
		this.name=name;
		this.age=age;
		this.salary=salary;
	}
	 //由于向上提取 都是工作功能定义相同,但内容不同	 定义为抽象  
	 //让继承的子类必须实现
	public abstract void work(); 

}
/*工人*/
class Worker extends Employee
{
	public Worker(String name, int age, double salary){
		  super(name,age,salary);
	}
   	public void work(){
		System.out.println(getName()+"工人");
	}
}
/*经理*/
class Manager extends Employee
{
   private double tiCheng;
   public void setTiCheng(double tiCheng){
   	   this.tiCheng=tiCheng;
   }
   public double getTiCheng(){
		return tiCheng;
   }
   public Manager(String name, int age, double salary,double tiCheng){	
	   super(name, age, salary);
	   this.tiCheng=tiCheng;
   }
   public void work(){
		System.out.println(getName()+"经理");
	}
}



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


暴露出去不一定是abstract,也有可能会有初始化内容.
/*
模板设计模式

获取一段程序的运行时间
*/
class Demo6 
{
	public static void main(String[] args) 
	{
		  System.out.println("毫秒"+new T().getTime());
		   System.out.println("毫秒"+new T1().getTime());
	}
}
/*
一部分确定的功能就是获取程序运行时间

不确定的就是要运行的程序 abstract
*/
abstract class Program
{
	/*程序确定的部分不能修改 用final*/
	public final long getTime(){
		long start=System.currentTimeMillis();

		want();

		long end=System.currentTimeMillis();

		return end-start;
	}
	public	abstract void want();
}
/*
只要继承 子类重写want() 调用父类的getTime()就可以 获取want()功能的运行时间 
*/
class T extends Program
{
	public void want(){
		for (int i=0;i<1000 ;i++ )
		{
			System.out.print(i);
		}
	}
}
/*
再来求一个程序的运行时间
*/
class T1 extends Program
{
	public void want(){
		int i=0;
		while(i<4000){
		   System.out.print(i);
		   i++;
		}
	}
}



接口(interface)


接口定义时,格式特点:
1.接口中常见定义:常量,抽象方法
2.接口中成员都有固定的修饰符
常量:public static final
方法:public abstract
记住:接口的成员都是public的


类与类是继承关系
类与接口是实现关系


/*
接口测试类
*/
class Demo7 
{
	public static void main(String[] args) 
	{
		System.out.println("Hello World!");
	}
}
/*final 不能修饰接口*/
interface Inter
{	/*
	接口没有构造函数
	public Inter(){
	
	}
	*/
	//int a;//接口不能有变量

	//接口常定义常量,抽象方法
	public final static double PI=3.14;
	
	/*讲话*/
	public abstract void speak();
}
/*

//接口可以多继承,多实现	 错误演示

interface A
{
   public abstract void show();
}
interface B
{
	public abstract int show();
}
interface C extends A,B //多继承
{
	//继承的时候两个相同的show jvm不知道调用那个 会报错
	//这是不能有同名show方法(包括返回值类型相同)
}
*/
//接口可以多继承,多实现

interface A
{
   public abstract void show();
}
interface B
{
	public abstract int method();
}
interface C extends A,B //多继承
{
	public abstract void eat();
}


class One implements Inter,C //多实现
{
	public void show(){}
	public int method(){
	return -1;}
	public void eat(){
	
	}
	public void speak(){
	} 
	
}



实现接口的关键字:implements


接口是不可以创建对象的,因为存在抽象方法,需要被子类实现,子类是
对接口中的全部覆盖后才可以实例化的,否则子类就是一个抽象类


接口的特点:
1.接口是对外暴露的规则
2.接口是程序的功能扩展
3.接口可以被类多实现
4.接口之间可以多继承.


接口与类的所属关系是: like a (你像谁中的一个)


class Demo8 
{
	public static void main(String[] args) 
	{
		new Pupil("z",15).study();
		new MidStu("d",157).study();
	}
}
abstract class Student
{
   private String name;
   private int age;	 
   public void setName(String name){
		this.name=name;
	}
	public String getName(){
		return name;
	}
	public void setAge(int age){
		 this.age=age;
	}
	public int getAge(){
		 return age;
	}
	public Student(String name, int age){
		this.name=name;
		this.age=age;
	}
   /*学习内容不确定*/
   public abstract void study();
}
/*小学生*/
class  Pupil extends Student//Pupil
{
  public Pupil(String name, int age){
	super(name,age);
  }
  public void study(){
	System.out.println("小学生学习小学内容");
  }
}

/*
接口是对外暴露的规则
接口是程序的扩展功能
*/
interface Smok
{
	public abstract void  smoking();
} 

/*中学生*/
class MidStu extends Student implements Smok
{
	public MidStu(String name, int age){
		super(name,age);
	}
	public void study(){
		System.out.println("中学生学习中学内容");
	}
	public void smoking(){
		System.out.println("中学生还会抽烟 ");
	}
}


 —————————— ASP.Net+Android+IOS开发.Net培训、期待与您交流!——————————

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值