面向对象(OOP)的三大特征:继承、封装、多态
一、封装性
为什么需要封装?封装的作用和含义?
我要用洗衣机,只需要按一下开关和洗涤模式就可以了。有必要了解洗衣机内
部的结构吗?有必要碰电动机吗?
我要开车,…
我们程序设计追求“高内聚,低耦合”。
高内聚
:类的内部数据操作细节自己完成,不允许外部干涉;
低耦合
:仅对外暴露少量的方法用于使用。
隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。通俗的说:
🧨把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想。
🎈信息的封装和隐藏
Java中通过将数据声明为私有的(private),再提供公共的(public)方法:getXxx()和setXxx()实现对该属性的操作,以实现下述目的:
1.隐藏
一个类中不需要对外提供的实现细节;
2.使用者只能通过事先定制好的方法来访问数据,可以方便地加入控制逻辑, 限制对属性的不合理操作;
3.便于修改,增强代码的可维护性;
/*
* 面向对象的特征一:封装与隐藏 3W:what? why? how?
* 一、问题的引入:
* 当我们创建一个类的对象以后,我们可以通过"对象.属性"的方式,对对象的属性进行赋值。这里,赋值操作要受到
* 属性的数据类型和存储范围的制约。除此之外,没有其他制约条件。但是,在实际问题中,我们往往需要给属性赋值
* 加入额外的限制条件。这个条件就不能在属性声明时体现,我们只能通过方法进行限制条件的添加。(比如:setLegs())
* 同时,我们需要避免用户再使用"对象.属性"的方式对属性进行赋值。则需要将属性声明为私有的(private).
* -->此时,针对于属性就体现了封装性。
*
* 二、封装性的体现:
* 我们将类的属性xxx私有化(private),同时,提供公共的(public)方法来获取(getXxx)和设置(setXxx)此属性的值
*
* 拓展:封装性的体现:① 如上 ② 不对外暴露的私有的方法 ③ 单例模式 ...
*
*
* 三、封装性的体现,需要权限修饰符来配合。
* 1.Java规定的4种权限(从小到大排列):private、缺省(什么也不写)、protected 、public
* 2.4种权限可以用来修饰类及类的内部结构:属性、方法、构造器、内部类
* 3.具体的,4种权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类
* 修饰类的话,只能使用:缺省、public
*
* 总结封装性:Java提供了4种权限修饰符来修饰类及类的内部结构,体现类及类的内部结构在被调用时的可见性的大小。
*
*/
public class AnimalTest {
public static void main(String[] args) {
Animal a = new Animal();
a.name = "大黄";
// a.age = 1;
// a.legs = 4;//The field Animal.legs is not visible
a.show();
// a.legs = -4;
// a.setLegs(6);
a.setLegs(-6);
// a.legs = -4;//The field Animal.legs is not visible
a.show();
System.out.println(a.name);
}
}
class Animal{
String name;
private int age;
private int legs;//腿的个数
//对属性的设置
public void setLegs(int l){
if(l >= 0 && l % 2 == 0){
legs = l;
}else{
legs = 0;
// 抛出一个异常(暂时没有讲)
}
}
//对属性的获取
public int getLegs(){
return legs;
}
public void eat(){
System.out.println("动物进食");
}
public void show(){
System.out.println("name = " + name + ",age = " + age + ",legs = " + legs);
}
//提供关于属性age的get和set方法
public int getAge(){
return age;
}
public void setAge(int a){
age = a;
}
}
二、继承性
为什么要有继承?
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中, 那么多个类无需再定义这些属性和行为,只要继承那个类即可。
此处的多个类称为子类(派生类)
,单独的这个类称为父类(基类或超类)
。可以理解为:“子类 is a 父类”
类继承语法规则:
class Subclass extends
SuperClass{ }
🎨作用:
继承的出现减少了代码冗余,提高了代码的复用性。
继承的出现,更有利于功能的扩展。
继承的出现让类与类之间产生了关系,提供了多态的前提
。
注意:不要仅为了获取其他类中某个功能而去继承
子类继承了父类,就继承了父类的方法和属性。
在子类中,可以使用父类中定义的方法和属性,也可以创建自己特有的新的属性和方法。
在Java 中,继承的关键字用的是“extends”,即子类不是父类的子集,而是对父类的“扩展”。
关于继承的规则:仍然认为获取了父类中的私有结构,只是因为封装性的影响,子类不能直接访问父类中私有的(private)的成员变量和方法。
- 一个类可以被多个子类继承
- Java中类的单继承性:一个类只能有一个父类
- 子父类是相对的概念
- 子类直接继承的父类,称为:直接父类。间接继承的父类称为:间接父类
三、多态性
1.多态性的使用
创建Person类
package com.atguigu.java4;
public class Person {
String name;
int age;
int id = 1001;
public void eat(){
System.out.println("人:吃饭");
}
public void walk(){
System.out.println("人:走路");
}
}
创建Man继承Person
package com.atguigu.java4;
public class Man extends Person{
//获得Person中属性和方法的同时,添加Man特有的属性和方法
boolean isSmoking;//是否抽烟
int id = 1002;
public void earnMoney(){
System.out.println("男人负责挣钱养家");
}
//重写eat方法
public void eat(){
System.out.println("男人多吃肉,长肌肉");
}
public void walk(){
System.out.println("男人霸气的走路");
}
}
创建Woman继承Person
package com.atguigu.java4;
public class Woman extends Person{
boolean isBeauty;//是不是美女
public void goShopping(){
System.out.println("女人喜欢购物");
}
public void eat(){
System.out.println("女人少吃,为了减肥");
}
public void walk(){
System.out.println("女人窈窕的走路");
}
}
通过测试说明叫多态性
package com.atguigu.java4;
/*
* 面向对象特征之三:多态性
*
* 1.理解多态性:可以理解为一个事物的多种形态。
* 2.何为多态性:
* 对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)
*
* 3. 多态的使用:虚拟方法调用
* 有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。
* 总结:编译,看左边;运行,看右边。
*
* 4.多态性的使用前提: ① 类的继承关系 ② 方法的重写
*
* 5.对象的多态性,只适用于方法,不适用于属性(编译和运行都看左边)
*/
public class PersonTest {
public static void main(String[] args) {
//最原始的调用,这里和多态性没什么关系
Person p1 = new Person();
p1.eat();
Man man = new Man();
man.eat();
man.age = 25;
man.earnMoney();
//*************************************************
//对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)
Person p2 = new Man();
// Person p3 = new Woman();
//多态的使用:当调用子父类同名同参数的方法时,实际执行的是子类重写父类的方法 ---虚拟方法调用
p2.eat();//打印“男人多吃肉,长肌肉”
p2.walk();//点进去是父类的方法
//只能调用Person里面声明的方法
//编译看左边,没有的方法会报错。执行看右边,实际执行重写后的方法
// p2.earnMoney();
System.out.println(p2.id);//1001
}
}
2.多态性的使用举例
如果没有多态性,还需要写另外两个重载的func方法
package com.atguigu.java4;
import java.sql.Connection;
//多态性的使用举例一:
public class AnimalTest {
public static void main(String[] args) {
AnimalTest test = new AnimalTest();
//调用func方法,首先需要传一个实例,多态性可以new子类对象
test.func(new Dog());//相当于Animal animal = new Dog();
test.func(new Cat());//相当于Animal animal = new Cat();
}
public void func(Animal animal){//Animal animal = new Dog();
animal.eat();//具体调用父类还是子类的方法看传入的对象
animal.shout();
if(animal instanceof Dog){
Dog d = (Dog)animal;
d.watchDoor();
}
}
//没有多态性调用时,需要写额外的重载func方法
// public void func(Dog dog){
// dog.eat();
// dog.shout();
// }
// public void func(Cat cat){
// cat.eat();
// cat.shout();
// }
}
//父类
class Animal{
public void eat(){
System.out.println("动物:进食");
}
public void shout(){
System.out.println("动物:叫");
}
}
//dog子类
class Dog extends Animal{
public void eat(){System.out.println("狗吃骨头");}
public void shout(){System.out.println("汪!汪!汪!");}
public void watchDoor(){System.out.println("看门");}
}
//cat子类
class Cat extends Animal{
public void eat(){System.out.println("猫吃鱼");}
public void shout(){System.out.println("喵!喵!喵!");}
}
//举例二:
class Order{
public void method(Object obj){
}
}
//举例三:
class Driver{
public void doData(Connection conn){//conn = new MySQlConnection(); / conn = new OracleConnection();
//规范的步骤去操作数据
// conn.method1();
// conn.method2();
// conn.method3();
}
}