面向对象,无论什么编程语言,都有三个特点:封装,继承,多态。

首先,封装:

    举个例子,比如电脑,电脑就是一个类,外面有些usb插口,你知道,把打印机插上就可以打印,把音响插上可以放音乐,但是你并不知道电脑内部是怎么实现的,你只是知道这个接口确实有这些功能,你就可以用了,这样,对普通用户,他们不了解电脑,也能用,不至于去破坏电脑内部的东西。而开发人员就是预留这些接口,保护电脑不会被不专业的人搞坏了。

    封装就是做这个事情,类就是黑盒子,预留几个接口让别人用,怎么实现的那个使用的人不需要知道。

    例如,有一个电脑类,属性:品牌,型号两个,让外面可以通过接口访问这两个属性,但是又不能直接对属性访问。代码如下:

    

/**
*@author LeiGao
*@data 2016.11.19
*/

class Computer{
	//将两个属性私有化,外面就不可以访问了。
	private String brand;
	private String type;
	
	//实现两个属性访问的接口,就是用方法来作为接口,如下:
	public String getBrand(){
		return brand;
	}
	public void setBrand(String brand){
		this.brand=brand;
	}
	
	public String getType(){
		return type;
	}
	public void setType(String type){
		this.type=type;
	}
}

//指定程序入口:
class ComputerMain{
	public static void main(String[] args){
		Computer computer = new Computer();
		//下面两个语句会报错:
			//computer.brand="lenovo";
			//computer.type="thinkpad"
		
		//通过接口设置属性和访问属性
			//设置属性
		computer.setBrand("lenovo");
		computer.setType("thinkpad");
		
			//访问属性
		String brand = computer.getBrand();
		String type = computer.getType();
		
		System.out.println("品牌:"+brand+"\n类型:"+type);
	}
}

注:java权限修饰符,在成员变量与成员方法前,也就是类的属性和功能前。主要限制外来人员的访问,以保证其安全性。具体权限,如下图:

    

wKioL1gv40WC8J5tAAGlFD6nKXk142.png-wh_50

从上图可以看出,作为接口或者功能的成员方法,本来就是为了让其他模块或者其他人使用,因此除了特殊情况,基本都用public修饰,作为类的属性的成员变量,为了保护,基本都用private修饰,其他关键字很少使用。


其次,继承:

    所谓继承,就是子继承父,既然继承父亲了,那么父亲会的,孩子都会,父亲不会的,孩子也可以会,要不然怎么有进步呢?当然private修饰的孩子没有,但是public修饰的有,因此,被private修饰的属性的接口,setter和getter方法,依然有用。

    uml类图如下:

    

wKioL1gv5ivTSXxKAAAp8K8XOLo275.png-wh_50

根据上图,实现的代码如下:

/**
 * @author LeiGao24
 * @data 2016.11.19
 */
 
 class Person{
	 private String name;
	 private String sex;
	 private Integer age;
	 
	 public void sleep(){
		 System.out.println("person sleep ...");
	 }
	 
	 public void eat(){
		 System.out.println("person eat ...");
	 }
	 
	 //成员变量的接口
		//name接口
	 public void setName(String name){
		 this.name=name;
	 }
	 public String getName(){
		 return name;
	 }
		//sex接口
	 public void setSex(String sex){
		 this.sex=sex;
	 }
	 public String getSex(){
		 return sex;
	 }
		//age接口
	 public void setAge(Integer age){
		 this.age=age;
	 }
	 public Integer getAge(){
		 return age;
	 }
 }
 
 class Teacher extends Person{
	 //teacher所属学校
	private String school;
	
	 //成员方法
	 public void teach(){
		 System.out.println("Teacher 的 teach 方法...");
	 }
	 
	 //school接口
	 public void setSchool(String school){
		 this.school=school;
	 }
	 public String getSchool(){
		 return school;
	 }
	
 }
 
 class Student extends Person{
	 //学生所属班级,因为class为关键字,所以写为cls
	private String cls;
	
	 //成员方法
	 public void study(){
		 System.out.println("Student 的 study 方法...");
	 }
	 
	 //school接口
	 public void setCls(String cls){
		 this.cls=cls;
	 }
	 public String getCls(){
		 return cls;
	 }
 }
 
 //程序入口
 class personMain{
	 public static void main(String[] args){
		 //创建:
			//人:张三,男,21岁
			//老师:李四,男,30岁,清华附中
			//学生:王语嫣,女,18,高三二班
		System.out.println("******人**********");	
		Person person = new Person();
		person.setName("张三");
		person.setSex("男");
		person.setAge(21);
		System.out.println("姓名:"+person.getName()+"\n性别:"+
			person.getSex()+"\n年龄:"+person.getAge());
			
		System.out.println("*******老师*******");
		Teacher teacher = new Teacher();
		teacher.setName("李四");
		teacher.setSex("男");
		teacher.setAge(30);
		teacher.setSchool("清华附中");
		System.out.println("姓名:"+teacher.getName()+"\n性别:"+
			teacher.getSex()+"\n年龄:"+teacher.getAge()+
			"\n所属学校:"+teacher.getSchool());
			
		System.out.println("*******学生********");
		Student student= new Student();
		student.setName("王语嫣");
		student.setSex("女");
		student.setAge(18);
		student.setCls("高三二班");
		System.out.println("姓名:"+student.getName()+"\n性别:"+
			student.getSex()+"\n年龄:"+student.getAge()+
			"\n所属班级:"+student.getCls());
		
	 }
 }

运行结果:

    wKioL1gv7Xfil6dmAAAS9T0YHX8983.png-wh_50


最后,多态:

    多态就是同一种东西但是有多个形态,或者说类型比较多,但是本质上是一个东西,比如冰箱,这就是一种东西,但是又分很多类,比如,海尔,美的,等很多品牌。本质上就是一个东西,这就是多态了。

    多态分为两种:一种是运行时多态,一种是编译时多态。

    运行时多态,就是上面举的冰箱的例子,冰箱是一个类,海尔是一个类,里面都有制冷的方法,只是海尔冰箱会重写制冷的方法。这种多个类,类间重写的方式,就是运行时多态

    编译时多态,比如,吃火锅的时候,放进去菜,煮熟的就是菜,放进去肉煮熟的就是肉,并没有肉一个锅,菜一个锅,而是在一个锅里,你放进去什么,他就是按照你放的东西进行处理,这种在一个类里面,有多个重名的方法,只是方法的参数不一样的实现方式,就叫做重载,也就是编译时多态。


    多态的实现方式有三种:

        第一种,实现接口

        第二种,继承

        第三种,实现抽象类

    所谓接口,就是扩展类的一种方式,类似电脑上的usb接口。比如,手机类继承关系。如下图:

    

wKioL1gv9cKAI8qOAAAZI6hkCT8925.png-wh_50

    从上图我们看出,三星,苹果,诺基亚都是手机,所以是继承关系(用“is-a”表示这种关系),但是我们会发现三星和苹果手机还有打游戏和看电影的功能,既然都有,为了减少代码量,我们可以把他们提取出来,但是提取出来以后又不能重新定义一个类,因为打游戏和看电影只有两个方法,没有什么类这个样子,【注意:不要提取出来就写一个类,一定是真正的类,现实中真能那样分类,不要为了继承而写类】,既然不能成立一个类,而打游戏和看电影这两个功能实际上是三星和苹果一类智能手机的扩展功能,所以我们可以直接提取出来写一个接口。UML图如下:

wKiom1gv97uSF_YwAAAay1Fsu28461.png-wh_50


第二种方式,继承,我们已经接触过多次了。

第三种方式,实现抽象类,既有继承,又有接口的特性

    比如,下面代码为一个抽象类,abstract修饰,只要含有一个抽象方法,这个类就是抽象类,使用的时候用继承关键字extends,接口一旦实现必须实现接口中的所有方法,抽象类则不必。下面代码演示:

/**
*@author LeiGao24
*@data 2016.11.19
*/

//定义一个手机类
class Phone{
	private String brand;
	private String size;
	
	//属性的setter和getter方法
	public void setBrand(String brand){
		this.brand = brand;
	}
	public String getBrand(){
		return brand;
	}
	
	public void setSize(String size){
		this.size=size;
	}
	public String getSize(){
		return size;
	}
}

//定义一个接口
	//接口中只定义扩展功能,也就是方法,并且方法
	//没有方法体,也就是没有大括号那部分
interface Func{
	public void playGame();
	public void Movies();
}

//定义一个抽象类:
	//抽象类和普通类一样,里面可以有属性和方法,
	//方法可以有方法体,也可以没有,而接口一定
	//没有方法体

abstract class FuncCls{
	public abstract void playGame();
	public void Movies(){
		System.out.println("打游戏...");
	}
}

//定义一个三星类,继承手机类,实现接口
class Sanxing extends Phone implements Func{
	//实现接口中所有的方法,如果有一个方法没实现,
	//就会报错
	public void playGame(){
		System.out.println("三星打游戏!");
	}
	public void Movies(){
		System.out.println("三星看电影。。。");
	}
}

//定义一个苹果类,继承抽象方法,因为java是单继承的
//所以只能继承一个类,但是java是多实现的,也就是说
//接口的实现可以是多个

class Apple extends FuncCls{
	private String brand;
	private String size;
	
	//实现抽象类中的抽象方法,如果不实现其中的
	//抽象方法,那么需要把类上标识abstract,表示
	//本类有抽象方法,是一个抽象类。
	
	public void playGame(){
		System.out.println("苹果玩游戏...");
	}
	
	
	//属性的setter和getter方法
	public void setBrand(String brand){
		this.brand = brand;
	}
	public String getBrand(){
		return brand;
	}
	
	public void setSize(String size){
		this.size=size;
	}
	public String getSize(){
		return size;
	}	
}

//程序入口:
class Main{
	public static void main(String[] args){
		Sanxing sanxing = new Sanxing();
		sanxing.playGame();
		sanxing.Movies();
		
		Apple apple = new Apple();
		apple.playGame();
		apple.Movies();
	}
}

结果:

    wKioL1gv_q6j_QFfAAAKLp5hMsk407.png-wh_50


总结:抽象类是提取具体类的公因式,而接口是为了将一些不相关的类“杂凑”成一个共同的群体。通常我们平时养成良好的习惯就是多用接口,毕竟Java是单继承的,只有在实现接口的时候才是多实现的。