Java05-2 面向对象的三大特征和五大原则

一、面向对象的三大特征
(一)继承:多个类中都要使用到一些相同的属性或者方法,我们可以将这些属性和方法定义在一个公共类中,需要这些属性和方法的类,只要继承该公共类,就可以直接使用,不用在自己的类中定义。
将公共类叫做父类、基类、超类;继承父类的类叫做子类、派生类
优点:
简化代码;
扩展性,不用改变原有代码的情况下扩展出新功能。

1.java中类只能有一个父类,单继承   (一个子类只能继承一个父类)
2.继承具有传递性
eg:A: name
       B  extends A
       C  extends B
       C也具有name属性
3.继承的关键字是extends
子类扩展于父类
class 子类    extends 父类{

}
注意:
在java中Object类是根类;
所有的类都直接或者间接的继承自Object  
如果一个类没有显式的继承一个父类,默认的父类为Object(Object可为最初父类的父类)

(二)多态:一个事物或者一种行为表现出不同的状态或者形态
优点:
重写的扩展性和灵活性,子类继承父类后,如果父类实现方法的功能不满足需要才重写,在重写时不需要再改父类的代码,相当于拥有了父类的功能,可以任意的扩展,或者在子类中按照自己的需求修改功能的实现过程,修改时,修改时,通过super拥有父类功能的同时,再添加额外的功能;
重写发生在运行时,运行时根据具体的对象调用本身的方法,不会混乱。

1.重写(override):在子类中重写父类中的某些方法
使用场景:子类继承了父类中的方法,但是父类中方法的实现不符合子类的需求,子类就需要重写父类的方法
重写判断标准:子类中方法的返回值和方法名必须和父类一样;
                        参数列表中参数的个数以及对应位置的参数类型必须一样,但参数名无所谓(可以不一样)
                      (方法体不一样)
注意:
自己类中定义了该方法,就调用自己的;未定义,就调用父类的该方法
重写时,该方法的访问范围不能比父类的小

 @xxx:注解  
 @Override添加到方法上,可以检查该方法是否是重写的方法
           不是重写的方法的话,编译期间会报错;如果是,不报错 
自己类中定义了该方法,就调用自己的;未定义,就调用父类的该方法
eg:class Animal{
               void sleep() {
        System.out.println("睡觉的方法");
        }
       class Lion extends Animal{
                @Override
                void sleep() {
                        System.out.println("狮子的睡觉方式");
                //void sleep(int a) {}    (该行非重写)
         }

       public class MyInherit {
    public static void main(String[] args) {
                     Lion lion = new Lion();
                     lion.sleep();    //此行打印 狮子的睡觉方式
              }
        }

2.重载(overload)
重载判断标准:方法名一样,参数列表不同,就是重载(其余部分,比如返回值类型都不管)
( 参数列表中参数的个数以及对应位置的参数类型不同)
(没有父类也可重载,不需要接收父类,在自己类里面重载自己的方法;
重载之后,调用时,主要根据实参列表来区分,参数列表的数据类型为父类类名,优先执行子类同方法名的方法体,子类没有就执行父类同方法名的方法体)
eg:
class Lion extends Animal{
         void run() {
                System.out.println("奔跑");
         }
         void run(String dest) {
                System.out.println("请跑到" + dest);
         }
}

public class MyInherit {
    public static void main(String[] args) {
                     Lion lion = new Lion();
                     lion.run();        //调用无参    奔跑
                     lion.run("河边");    //调用有参    请跑到河边
    }
}

重写和重载的区别:
重写要求返回值类型、方法名、参数列表必须和父类中的一致;重载方法名一样,参数列表不同;
重写必须发生在父子类之间;重载不需要,可以重载自己的方法。
1、定义不同:重载是定义相同的方法名、参数不同,重写是子类重写父类的方法
2、范围不同:重载是在一个类中,重写是子类与父类之间的
3、多态不同:重载是编译时的多态性,重写是运行时的多态性
4、参数不同:重载的参数个数、参数类型、参数的顺序可以不同,重写父类子方法参数必须相同
5、修饰不同:重载对修饰范围没有要求,重写要求重写方法的修饰范围大于被重写方法的修饰范围
    
3.父类引用,引用子类对象
祖先类型 对象名 = new 子孙类();
代码执行分两个阶段
1.编译期
2.运行时
在编译期 调用方法或者变量,根据声明类型来判断是否可以调用。
只有当运行起来之后(运行时),会根据对象具体的类型去调用对应的方法
 方法重写之后,调用的是哪个方法,看new部分(具体的对象的类型)
父子类中有同名的成员变量,使用的是哪个成员变量,看声明的类型即可
例如 声明的类型是Animal,那就使用Animal中的该成员变量
eg:class Animal{
               int age = 10;
               void sleep() {
                System.out.println("睡觉的方法");
              }
        }
       class Lion extends Animal{
                int age = 100;
                void sleep() {
                System.out.println("狮子的睡觉方式");
               }
         }

       public class MyInherit {
    public static void main(String[] args) {
            Animal animal = new Lion();  //此时编译时无Lion对象,运行时有
            animal.sleep();    //此行打印 狮子的睡觉方式
            System.out.println(animal.age);   //打印 10
                     //(此处声明哪个类型,就用哪个里面的成员变量)
            //Animal animal = new Lion();   animal.age打印10
            //Lion animal = new Lion();        animal.age打印100
              }
        } 
        
//(Dog lion = (Dog)animal;没有继承关系不能强转,有风险)
如何判断animal是否可以转换为Dog类型??
 instanceof:  (用来判断对象类型)
形式:对象名  instanceof 类名    ,会得到一个布尔值,true就是属于,false就是不属于
判断该对象 是否属于 该类型
 null instanceof 任何类   返回值都是false
 对象 instanceof 真实类型(具体类型)或者该类的祖先类  返回值都是true
System.out.println(null instanceof Object);   //打印false
System.out.println(animal instanceof Object);   //打印出true

//animal.run();    //此处编译期间animal无run方法,报错,需强转        
强转 
Lion lion = (Lion)animal;    //此处未new,lion和animal引用同一内存空间,是同一对象
System.out.println(lion);            //com.lanou.inherit.Lion@2a139a55
System.out.println(animal);     //com.lanou.inherit.Lion@2a139a55
lion.run();     //强转后等同于animal.run();    打印 奔跑 

animal = new Dog();         //该行new Dog();,以下打印animal是Dog 
if(animal instanceof Dog) {
    Dog lion = (Dog)animal;
    System.out.println("animal是Dog");
}else if(animal instanceof Lion) {
    Lion lion = (Lion)animal;
    System.out.println("animal是Lion");
}else {
    System.out.println("animal不知道是什么");
}
// new Lion();打印animal是Lion

举例:数组存入多种类型数据
Object[] ob = new Object[] {1,"aa",1.5,new Dog(),new Animal()};

(三)封装:将数据和操作封装起来,尽可能的隐藏操作的实现细节,让使用者只关心该对象的功能如何使用,不用关心实现过程
将数据和功能都隐藏起来,配合访问控制符,限制使用者能访问哪些数据,如何访问这些数据;不能访问哪些数据和方法


二、面向对象的五大原则
    1.单一职责原则(SRP)
一个类应该有且只有一个去改变它的理由,这意味着一个类应该只有一项工作。
    2.开放封闭原则(OCP)
对象或实体应该对扩展开放,对修改封闭。
更改封闭即是在我们对模块进行扩展时,勿需对源有程序代码和DLL进行修改或重新编译文件!这个原则对我们在设计类的时候很有帮助,坚持这个原则就必须尽量考虑接口封装,抽象机制和多态技术!
    3.里氏替换原则(LSP)
在对象 x 为类型 T 时 q(x) 成立,那么当 S 是 T 的子类时,对象 y 为类型 S 时 q(y) 也应成立。(即对父类的调用同样适用于子类)
    4.依赖倒置原则(DIP)
高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。具体实现应该依赖于抽象,而不是抽象依赖于实现。
    5.接口隔离原则(ISP)
不应强迫客户端实现一个它用不上的接口,或是说客户端不应该被迫依赖它们不使用的方法,使用多个专门的接口比使用单个接口要好的多!
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值