文章目录
前言
java中经常会把需要使用到的数据结构来封装成对象,而当我们这些后来希望使用前辈留下来的代码或者自己拓展功能供大家借鉴使用,面向对象是学习java中十分重要的部分。这里再次巩固java基础给大家带来一点自己的见解。
面向对象
1、什么是面向对象
面向对象的编程思想就是把事物看作一个整体,从事物的特征(属性)和行为(方法)两个方面进行描述。面向对象的过程就是找对象、建立对象、使用对象、维护对象的关系的过程。如果这个概念不是很直白,举例而言,在解决现实中实际问题的时候,难免遇到需要用代码表示的对象,比如学生某某,那我们就可以把学生某某定义成一个对象,这个代码层面上的对象就可以完成学生某某的所有功能,而这种形式就称为面向对象。
2、面向对象的三大特性
面向对象的三大特征就是封装,继承,多态。
2.1 封装特性
封装,顾名思义也就是将信息封装到一起,封装完成之后的信息便于统一管理,但既然特地实现了信息封装隐藏,实现封装就可以自主控制是否要把封装后的信息展示给别人,那么在这里就需要提到修饰符的区别。
存在四种访问权限分别是public,protected,默认以及private。其中大家最熟悉的肯定是public和private,那么四者的区别就在于谁可以访问到当前对象。
- public 对外公开,访问权限最高
- protected 对当前所在包的类以及子类公开(子类设计到继承,不了解可以往下看)
- 默认 对当前所在包的类公开
- private 不对外公开,只能在对象内部访问,访问级别最低。
在了解了访问权限之后,那么接下来就到了如何封装这一问题上了,这里给大家举个实例
public class Student {
//成员变量
private String name;
//成员方法
public void study(){
System.out.println("学生在学习");
}
}
一个类应该包含成员变量以及成员方法,变量对应的就是属性,而方法对应的是行为,比如现实生活中的学生都应该有名字,那么在类中就应该含成员变量name,而学生这种群体有学习行为,所以在成员方法中就有study方法,那我们就成功的把属性和方法封装到了一起,实现了封装。
2.2 继承特性
继承本质上是让某一类对象获得另一类对象的属性和方法,这种特性很好的解决了代码重复编写的问题,比如说现在我们要写鸡鸭牛三种对象,那么三种对象现实生活里都有吃饭这一个行为,难道我们要在三个类都编写eat成员方法吗,而且现实里可还有许多的有吃饭行为的生物,所以为了防止重复编码,我们就可以编写一个统一的类,让凡是有这一行为的类直接继承它,这样就解决了问题,这就是面向对象中常说的继承特性。如果上述的描述还是略微抽象,接下来就拿鸡鸭举例,首先继承的语法是:
public class 子类名 extends 父类名
通过extends关键字和类名实现继承,那现在我们就可以来举例了。鸡鸭都是动物我们可以把它们的父类定义为animal类
public class animal {
public void eat(){
System.out.println("动物吃饭");
}
}
public class chicken extends animal{
}
public class duck extends animal{
}
那么我们在继承了以后就可以测试是否真的完成了对父类方法的获取
public class JavaTest4 {
public static void main(String[] args) {
chicken c = new chicken();
duck d = new duck();
d.eat();
c.eat();
}
}
最终控制台的结果说明方法正常运行,两个子类确实继承到了父类的方法。
但是继承本身却不只是这样,比如说学生,他在是人类的同时又是动物,那这个时候难道继承两个父类,那如果有其他身份,再继承别的父类吗?在java中明确规定了继承只能继承一个父类,父类是唯一的,那么如何解决上述提到的问题,java中通过多重继承来实现,比如说人类就是具有动物属性,那么在上述例子中,student类可以继承person类,person类可以继承animal类,通过多重继承最终实现属性的代代传递,大家应该明白的是继承到的应该是共同的部分,那么越往上方继承,要求大家都有的共性就会越少。举例说明假设animal中只有eat这一个方法,person继承了以后因为人都会使用工具,我们可以在person中写tool方法,那么在student类中可以继承到两个方法,因为鸡鸭不会使用工具所以这个tool方法不能向上提取到animal中只能放在person类中,因为这不是共性,所以就这个例子足以体现,越上方的类所具有的属性和方法就越少。
在解决了继承的基本问题后,在实际开发中又出现了新的问题,当我不想要父类的方法,想要对父类传下来的方法进行修改变成属于自己的方法,解决这个问题的方法就是java中的重写。
首先重写要满足几个条件:
- 父类被重写的方法与子类重写的方法的方法名和形参列表必须相同,这保证了在调用方法时,编译器能够正确地识别和匹配方法。
- 父类子类的返回值类型相同,其中引用数据类型略有不同,子类的返回值类型可以相同或是被重写的方法的返回值类型的子类。
- 子类重写的方法权限修饰符不能低于父类的权限修饰符,这是为了保证子类在重写方法后,其可访问性不会低于父类方法。
在满足了以上条件后,我们就可以来重写方法,这里举例说明:
public class animal {
public void eat(){
System.out.println("动物吃饭");
}
}
public class chicken extends animal{
public void eat(){
System.out.println("鸡吃饭");
}
}
public class duck extends animal{
public void eat(){
System.out.println("鸭吃饭");
}
}
public class JavaTest4 {
public static void main(String[] args) {
chicken c = new chicken();
duck d = new duck();
d.eat();
c.eat();
}
}
最终控制台输出结果为:
说明方法成功被重写。
2.3多态特性
正如上面继承说的多重继承问题所聊到的,现实生活中事物存在多种形态,比如狗,既是动物也是宠物,那么这里所展现出来的就是多态这一特性。
多态的使用体现在父类引用变量可以指向子类类型。
父类类型 变量名称 = new 子类类型()
使用多态的前提自然是已经存在合理的父子类关系,个人理解而言,多态本质上是一类事物的具体化过程,比如说父类是人,人本身有很多职业,可以是律师,学生,厨师等等,如果是为了使用具体的子类中的方法,那么我们就可以具体指定是什么职业的人,也就类似于多态中指向哪种子类的父类引用变量。
那为什么说使用的是子类中的方法而不是属性呢,这里就要讲到编译的前后问题
- 多态成员变量:编译看左边父类类型,也就是说此时成员变量的值是父类中的值,与子类无关
- 多态成员方法:编译看左边,运行看右边,此时调用的方法是根据右边的子类类型决定的,方法是子类中的方法。
这里还是用上述例子:
public class animal {
public static String name ="动物";
public void eat(){
System.out.println("动物吃饭");
}
}
public class JavaTest4 {
public static void main(String[] args) {
animal c = new chicken();
animal d = new duck();
System.out.println(animal.name);
d.eat();
c.eat();
}
}
最终打印的结果完全符合预期,说明了多态的特性。但是多态中的指定只能限定在继承下来的方法上,假设说现在出现了子类中有而父类中没有的方法,那么为了使用子类中的特定功能,此时就需要使用向下转型
子类类型 变量名 = (子类类型)父类类型的变量名
在使用了向下转型后才能使用子类中特定的功能。
以上就是我对面向对象特性的一些见解,希望有所帮助。