面向对象编程思想
面向对象,简单来说就是由动作的执行者变为动作的操控者。结合具体例子来说就是使用某个人或者工具所具有的功能而不用去管功能的具体实现方式。例如现实中的项目开发,老板想要实现某些功能,但是他自己不会这些技术,所以他就会让员工去做这些事情,通过借助别的拥有你想要实现某些功能的过程就可以理解为面向对象。面向对象是相对于面向过程的。
类与对象
接着来了解下什么是 类与对象,世界是由什么组成的?我们这样考虑,世界是由动物、植物等组成的,动物又分为哺乳动物和非哺乳动物,哺乳动物又分为老虎、狮子、大象... ...可以继续分类下去。通过这个例子我们对人类进行分析,人都会直立行走、会说话、有两个眼睛一个鼻子、会使用工具、会劳动、会创造工具等特征,这就是人区别于其他动物的原因,当某个事物符合了人所具有的所有特征,我们就说他是一个人,老虎、狮子、海豚等不具备”人类“的某些特征,所以它们不是人。但是要注意:类不是具体的事物,而是由个体组成的集合。这样的个体就叫做对象。
所以,类描述了一组有相同特性(属性)和相同行为(方法)的对象。
面向对象三大特征
面向对象有三大特征,即封装、继承和多态。
<font color=red>封装</font>
封装,也就是隐藏,隐藏对象功能的实现细节和属性或者不需要用户知道的内容,只提供与外部联系的接口供用户使用。
封装的好处
1、减少代码的耦合性,使代码更加精简。
2、提高代码的复用性,不必再重复写功能相近的代码。
封装的具体实现就是将某一功能或属性抽离出来,独立写成单独的方法或类,对类及其属性和方法设置访问权限限定该功能或属性可以被特定的访问者访问,访问权限有public、protected、private和默认。
public:在任何类中都能访问,即使不在同一包中。
protected:只能在本包和子类中访问,即使子类不和父类在同一包中,也能访问到。
private:只能在本类中被访问,子类也访问不到。
默认:只能在同一个包中被访问到。
注意:类只能访问其他类的public和protected修饰的属性和方法,不能访问到private修饰的。
来看具体例子:
public class Person {
private String name;
private int age;
private String id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
这个简单的例子把人属性封装了进去,外部只能调用相应的get和set方法来对属性进行操作。
<font color=red>继承</font>
假设在描述某些事物的时候我们会发现他们具有许多相同的地方,例如鸟类,每种鸟都有眼睛,嘴巴,都会吃东西等,这些相同的地方可以把他们抽取出来定义成一个鸟类,当需要描述多种鸟时就不用再重复定义这些共性,直接继承鸟类即可,不必再重新续写重复内容。
注意:Java的继承不是像C++一样,Java只存在单继承且智只能继承父类的非私有成员,使用extends ,在调用子类构造方法时会调用父类无参构造方法,若父类没有无参构造,注意为其添加无参构造方法。super()方法可调用父类方法或变量。继承提高了程序的复用性、扩展性,也是 多态特征的前提。
super和this的区别:
super(参数):调用父类的某一构造函数
super.方法:调用父类中的方法;
super.变量名:调用父类中的变量
this:代表当前对象名
this与super如果要在构造函数里使用则都必须在构造函数的第一行,所以不能同时存在与构造函数里。
因为static不包含对象,this和super代表对象,所以不能在static域中使用super和this。
接口和抽象类
接口:interface 接口名{方法1;方法2…},默认修饰符为 public ,不能用其他修饰符修饰接口。
抽象类:当多个类都存在相同方法名,但是其实现方式却不相同时可以将它们进行抽取,定义成一个类,只有方法名没有具体实现,abstract class 类名{ abstract void…方法名();}
注意:仅实现抽象类的部分功能的类还是抽象类。抽象类除了不能被实例化外和正常类没什么区别。
接口与抽象类的区别:接口可以被实现多个中间用逗号隔开,使用 implements 关键字实现接口,实现了接口类必须全部实现接口中的方法。如果基本功能在不断改变,那么就需要使用抽象类。如果不断改变基本功能并且使用接口,那么就需要改变所有实现了该接口的类。抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;继承抽象类如果不实现所有的抽象方法,子类必须声明为抽象类。
java不支持多继承,但是可以实现多个接口,形如
class Main extends A implements B,C...{ }
稍微注意下,接口之间也可以继承,而且是可以多继承(了解一下就行了,基本不提这个)。
多态
多态是同一个行为具有多个不同表现形式或形态的能力。
多态存在的三个必要条件
继承
重写
父类引用指向子类对象
java的多态中涉及到向上转型和向下转型。
Father f = new Child();
上面的例子为向上转型,父类引用指向子类对象。
Father f = new Child();
Child c = (Child) f;
向下转型即当我们有一个父类对象时,我们想要实现子类中的某些方法功能时就需要向下转型,上面的例子为向下转型。
用一个具体的实例说明向上转型与向下转型
abstract class Animal{
public abstract void eat();
public abstract void sleep();
}
class Cat extends Animal{
public void eat()
{
System.out.println("猫吃鱼");
}
public void sleep()
{
System.out.println("猫睡觉");
}
public void ability()
{
System.out.println("猫抓老鼠");
}
}
class Dog extends Animal
{
public void eat()
{
System.out.println("狗吃骨头");
}
public void sleep()
{
System.out.println("狗睡觉");
}
public void ability()
{
System.out.println("狗看家");
}
}
public class DuoTai{
public static void main(String[] args){
Animal a = new Cat();//自动向上转型
a.sleep(); //Animal 类中定义了此方法,而子类中也重写了此方法,调用的是子类中的sleep()方法
a.eat();
//a.ability(); 编译失败,因为 a是父类Animal类的引用,而Animal类中未定义此方法,所以会报错
getAbility(a);
}
public static void getAbility(Animal a){
if(a instanceof Cat) {
Cat c = (Cat) a;//向下转型,使用instanceof关键字判断是否是指定类的对象
c.ability();
}
if(a instanceof Dog){
Dog d = (Dogs) a;
d.ability();
}
}
}
/**
* 执行结果为:
* 猫睡觉
* 猫吃鱼
* 猫抓老鼠
*/