JAVA面向对象(OOP)

1.面向对象与面向过程

面向对象程序设计(Object Oriented Programming)
Java是一门面向对象的语言
面向对象强调的是事情的结果,我们通过对象完成对应的功能
把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为

C语言是一种面向过程的语言,而C++却是一种面向对象的语言。在C++程序里,数据和对数据的处理都被封装在了一个对象里
面向过程强调的是事情的过程,我们做任何事情,都要亲力亲为,经过每一个步骤
两者都是一种编程的思想

例如五子棋
面向过程的设计思路就是首先分析问题的步骤:1、开始游戏,2、黑子先走,3、绘制画面,4、判断输赢,5、轮到白子,6、绘制画面,7、判断输赢,8、返回步骤2,9、输出最后结果。把上面每个步骤用分别的函数来实现,问题就解决了
面向对象的设计则是从另外的思路来解决问题。整个五子棋可以分为 1、黑白双方,这两方的行为是一模一样的,2、棋盘系统,负责绘制画面,3、规则系统,负责判定诸如犯规、输赢等。第一类对象(玩家对象)负责接受用户输入,并告知第二类对象(棋盘对象)棋子布局的变化,棋盘对象接收到了棋子的i变化就要负责在屏幕上面显示出这种变化,同时利用第三类对象(规则系统)来对棋局进行判定
结论
可以明显地看出,面向对象是以功能来划分问题,而不是步骤。同样是绘制棋局,这样的行为在面向过程的设计中分散在了总多步骤中,很可能出现不同的绘制版本,因为通常设计人员会考虑到实际情况进行各种各样的简化。而面向对象的设计中,绘图只可能在棋盘对象中出现,从而保证了绘图的统一
功能上的统一保证了面向对象设计的可扩展性。比如我要加入悔棋的功能,如果要改动面向过程的设计,那么从输入到判断到显示这一连串的步骤都要改动,甚至步骤之间的循序都要进行大规模调整。如果是面向对象的话,只用改动棋盘对象就行了,棋盘系统保存了黑白双方的棋谱,简单回溯就可以了,而显示和规则判断则不用顾及,同时整个对对象功能的调用顺序都没有变化,改动只是局部的

2.类与对象

定义类通过关键字class来定义,类是一类事物的抽象,它是抽象的,它是模板
创建对象通过new关键字触发构造函数生成,对象是根据类创建出来的具体的内容
一个类可以创建出多个对象,对象是根据类的设计来创建的,所以对象具有类的所有属性与功能
对象之间是相互独立的,互不影响。我们把创建对象也称作“实例化”

3.面向对象的三大特性

1,封装

前提:为了保证数据的安全,也为了程序的使用者能够按照我们预先设计好的方式来使用资源
封装属性:用private修饰我们的属性
然后为属性提供对应的getXxx()【获取属性值】与setXxx()【设置属性值】
封装方法:用private修饰方法,被修饰的方法只能在本类中使用,所以我们在本类的公共方法里调用这个私有方法
外界如果想要使用这个私有方法的功能,只需要调用这个公共方法就可以了

2,继承

前提 :继承可以实现程序的复用性,减少代码的冗余
我们通过extends关键字建立子类与父类的继承关系:格式:子类 extends 父类
继承相当于子类把父类的功能复制了一份,包括私有资源
注意:虽然私有资源继承了,但是私有资源不可用,原因是被private限制了访问,私有资源只能在本类使用
注意:构造方法不能继承,原因是:构造方法要求名字是本类的类名,我们不能在子类中出现父类名字的构造方法
继承是可以传递的:爷爷的功能会传给爸爸,爸爸的功能会传给孙子
注意:爸爸从爷爷那里继承的功能,也会一起传给孙子
Java的类是单继承的:一个子类只能有一个父类,但是一个父类可以有多个子类
子类在继承了父类以后,如果对父类的功能不满意
可以在不修改父类功能的【满足OCP原则】前提下,在子类中,重写继承过来的这个方法
重写需要满足的规则:两同 两小 一大,我们可以在重写的方法上加@Override注解验证是否写对
继承是一种is a的关系,强耦合,关联性特别强,而且类的继承机会只有一次,要谨慎使用
子类可以直接使用父类的所有非私有资源

package cn.tedu.oop;
import java.util.Random;
import java.util.Scanner;
/*本类用于复习面向对象的相关知识*/
public class TestOOP {
    public static void main(String[] args) {
        //8.提示并接收用户传入的宠物昵称
        System.out.println("请您输入宠物的名字:");
        String name = new Scanner(System.in).nextLine();
        //9.触发对应的构造函数,创建小猫类的对象
        Cat c = new Cat(name);
        //10.与宠物做互动
        System.out.println("按回车执行:");
        while(true){
            new Scanner(System.in).nextLine();
            int r = new Random().nextInt(6);
            switch (r){
                case 0:c.feed();break;
                case 1:c.play();break;
                default:c.punish();break;
            }
        }
    }
}
//1.创建父类:宠物类,描述宠物这一类事物
class Pet{
    //2.定义宠物类的属性
    String name;//电子宠物的姓名
    int full;//饱食度
    int happy;//快乐度

    //3.1 生成本类的全参构造
    public Pet(String name, int full, int happy) {
        this.name = name;
        this.full = full;
        this.happy = happy;
    }
    //3.2 创建本类的含参构造
    public Pet(String name){
        //只需要用户起宠物名即可,饱食度与快乐度的初始值都是50
        //实际上底层会触发全参构造,名字是用户起的,其他两个是预先设置好的默认值
        this(name,50,50);
    }
    //4.1定义宠物类的功能1--喂宠物吃东西
    public void feed(){
        //先判断宠物是不是吃饱了,如果吃饱了,结束整个喂食方法
        if(full == 100){
            System.out.println(name+"已经吃饱啦~");
            return;//遇到return关键字,整个方法直接结束
        }
        //如果没有吃饱,就给宠物喂食,一次增加10的饱食度
        System.out.println("给"+name+"喂食:");
        full = full + 10;
        System.out.println("饱食度:"+full);
    }
    //4.2定义宠物类的功能2--陪宠物玩
    public void play(){
        //先判断宠物还有没有饱食度,如果没有饱食度了,就不能玩了,结束整个玩的方法
        if(full == 0){
            System.out.println(name+"已经饿的玩不动了...");
            return;//遇到return关键字,整个方法直接结束
        }
        //如果饱食度不为0,就可以玩耍,每次玩耍快乐度+10,饱食度-10
        System.out.println("陪"+name+"玩耍");
        happy += 10;
        full -= 10;
        System.out.println("快乐度:"+happy);
        System.out.println("饱食度:"+full);
    }
    //4.3定义宠物类的功能3--宠物的惩罚方法
    public void punish(){
        System.out.println("打"+name+"的PP,哭叫声:"+cry());
        happy -= 10;
        System.out.println("快乐度:"+happy);
    }
    //4.4定义一个哭的方法--宠物被打哭了
    public String cry(){
        return "此处有哭叫声";//这个位置没有明确的叫声,因为子类会重写
    }
}

//5.创建子类小猫类
class Cat extends Pet{
    //6.由于父类的无参构造已经没有了,所以这里要手动调用父类的含参构造
    public Cat(String name) {//养猫的时候要给猫起昵称
        super(name);//表示调用父类的含参构造
    }
    //7.重写父类的cry();
    @Override
    public String cry(){
        return "喵~";
    }
}

3,多态

  1. 前提:为了忽略子类型之间的差异,统一看作父类类型,写出更加通用的代码
    比如:把Cat看作Animal,把Dog看作Animal,把Bird看作Animal,如果方法需要设置传入的参数,可以buy(Animal a)
    比如:把算术异常、输入不匹配异常都看作是Exception,统一捕获处理,只写一个解决方案
  2. 概念:在同一时刻,同一个对象,代表的类型不同,拥有多种形态
  3. 多态的要求:继承 + 重写
  4. 多态的口诀1:父类引用指向子类对象:父类型的引用类型变量保存的是子类对象的地址值
  5. 多态的口诀2:编译看左边,运行看右边:
    父类中定义的功能,子类才能使用,否则报错
    多态中,方法的定义看的是父类的,方法的实现看的是子类重写后的功能
    请添加图片描述
  6. 多态中资源的使用:
    1)成员变量:使用的是父类的
    2)成员方法:对于方法的定义看的都是父类的,对于方法实现,重写后使用的是子类的
    3)静态资源:静态资源属于类资源,不存在重写的概念,在哪个类中定义的,就属于哪个类
  7. 向上造型与向下造型
    1)这两种都属于多态,只不过是多态的两种不同的表现形式
    2)向上造型【最常用】
    可以把不同的子类型都看作是父类型,比如Parent p = new Child();
    比如:花木兰替父从军,被看作是父类型,并且花木兰在从军的时候,不能使用自己的特有功能,比如化妆
    3)向下造型
    前提:必须得先向上造型,才能向下造型
    子类的引用指向子类的对象,但是这个子类对象之前被看作是父类类型,所以需要强制类型转换
    Parent p = new Child(); 然后:Child c = (Child) p;
    比如:花木兰已经替她爸打完仗了,想回家织布,那么这个时候,一直被看作是父类型的花木兰必须经历“解甲归田”【强制类型转换】这个过程,才能重新被看作成子类类型,使用子类的特有功能
    为什么有向下造型:之前被看作是父类类型的子类对象,想使用子类的特有功能,那就需要向下造型
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值