Java面向对象

Java面向对象
       概要
    面向对象其实并不陌生,在PHP中也是有的:面向对象三大特性:继承 封装 多态。
其中涉及到两个基础概念:类和对象。
类:具有相同属性和方法的一组对象的集合
对象: 一个看得到、摸得着的具体实体
本篇文章通过对Java的学习,来加深对面向对象的理解。
       一、Java 封装(Encapsulation)
       在面向对象程式设计方法中,封装是指一种将抽象性函式接口的实现细节部份包装、隐藏起来的方法。 封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。
       1.  举个例子
       ATM机具有的功能-存取款、转账、余额查询...
    重要属性:钞票
正确的银行卡和密码
对于外部的储户而言,不关心在什么位置以什么形式存取钞票
既保障了重要信息(钞票)的安全性,同时又通过一系列外部接口实现了用户的便捷操作
对于储户而言,无论ATM内部结构发生怎样的变化,只要对外的接口不变,都是不影响的
      2. 封装的特性
      1)  将类的某些信息隐藏在类内部,不允许外部程序直接访问
      2)  通过该类提供的方法来实现对隐藏信息的操作和访问
      3)  隐藏对象的信息
      4)  留出访问的接口:要访问该类的代码和数据,必须通过严格的接口控制

      封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。

      适当的封装可以让程序代码更容易理解与维护,也加强了程序代码的安全性。

      3. 封装的实现

      修改属性的可见性:设为private 实现信息的隐藏

      getter/setter方法 设为public 用于属性的读写

      在getter/setter方法中加入属性控制语句:对属性值的合法性进行判断

 1 package wang.isee.animal;
 2 
 3 /**
 4  * 宠物猫类
 5  *
 6  * @author isee
 7  */
 8 public class Cat {
 9 
10     // 成员属性:昵称、年龄、体重、品种
11     // 修改属性的可见性--private 限定只能在当前类内访问
12     private String name; //昵称
13     int month; //年龄
14     double weight;//体重
15     String species;//品种
16 
17     //方法:跑动、吃东西
18 
19     public Cat() {
20         System.out.println("我是宠物猫~~");
21     }
22 
23     // 创建get/set方法
24     // 在get/set方法中添加对属性的限定
25     public void setName(String name) {
26         this.name = name;
27     }
28 
29     public String getName() {
30         return "我是一只名叫" + this.name + "的宠物猫";
31     }
32 
33 
34     public void setMonth(int month) {
35         this.month = month;
36     }
37 
38     public int getMonth() {
39         return this.month;
40 
41     }
42 
43     // 跑动的方法
44     public void run() {
45 
46         System.out.println("小猫快跑");
47 
48     }
49 
50     // 吃东西的方法
51     public void eat() {
52 
53         System.out.println("小猫吃鱼");
54     }
55 }

     二、Java 继承(Inheritance)

     Java继承是一种单继承方式,继承所描述的是“is-a”的关系,如果有两个对象A和B,若可以描述为“A是B”,则可以表示A继承B,

     其中B是被继承者称之为父类或者超类,A是继承者称之为子类或者派生类。

     子类拥有父类的所有属性和方法(除了private修饰的属性不能拥有)从而实现了实现代码的复用,

     简单来说,就是:父类更通用,子类更具体。

     1. 继承的特性

     1)子类拥有父类非private的属性、方法

     2)子类可以拥有自己的属性和方法,即子类可以对父类进行扩展

     3)子类可以用自己的方式实现父类的方法

  2.  构造器
除了那些private的外还有一样是子类继承不了的---构造器。对于构造器而言,它只能够被调用,而不能被继承。 调用父类的构造方法我们使用super()即可

构建过程是从父类“向外”扩散的,也就是从父类开始向子类一级一级地完成构建。而且我们并没有显示的引用父类的构造器,这就是java的聪明之处:编译器会默认给子类调用父类的构造器。
但是,这个默认调用父类的构造器是有前提的:父类有默认构造器。
如果父类没有默认构造器,我们就要必须显示的使用super()来调用父类构造器,否则编译器会报错:无法找到符合父类形式的构造器。

3. 方法重载和方法重写
1)方法重载(overload)
在同一个类中处理不同数据的多个相同方法名的多态手段;通俗来说一般是用于在一个类内实现若干重载的方法,这些方法的名称相同而参数形式不同
2)方法重写(override)
相对继承而言,子类中对父类已经存在的方法进行区别化的修改,通俗来说:重写方法的参数列表必须完全与被重写的方法的相同,否则不能称其为重写而是重载
3)方法重载和方法重写的区别
重写是由于继承关系中的子类有一个和父类同名同参数的方法,会覆盖掉父类的方法。重载是因为一个同名方法可以传入多个参数组合。
注意:同名方法如果参数相同,即使返回值不同也是不能同时存在的,编译会出错
4)编译时多态和运行时多态
从jvm实现的角度来看,重写又叫运行时多态,编译时看不出子类调用的是哪个方法,但是运行时操作栈会先根据子类的引用去子类的类信息中查找方法,找不到的话再到父类的类信息。
而重载则是编译时多态,因为编译期就可以确定传入的参数组合,决定调用的具体方法是哪一个了。
4. 继承的实现
 1 package wang.isee.inheritance;
 2 
 3 public class Shape {
 4     public static void main(String[] args) {
 5         Triangle tri = new Triangle();
 6         System.out.println("Triangle is a type of shape? " + tri.isShape()); //继承
 7         Shape shape = new Triangle();
 8         System.out.println("My shape has " + shape.getSides() + " sides."); //多态
 9         Rectangle rec = new Rectangle();
10         Shape shape2 = rec;
11         System.out.println("My shape has " + shape2.getSides(rec) + " sides."); //重载
12     }
13 
14 
15     public boolean isShape() {
16         return true;
17     }
18 
19     public int getSides() {
20         return 0;
21     }
22 
23     public int getSides(Triangle tri) { //重载
24         return 3;
25     }
26 
27     public int getSides(Rectangle tri) { //重载
28         return 4;
29     }
30 }
31 
32 
33 class Triangle extends Shape {
34     public int getSides() { //重写,实现多态
35         return 3;
36     }
37 }
38 
39 class Rectangle extends Shape {
40     public int getSides(int i) { //重载
41         return i;
42     }
43 }

   5.  谨慎继承
   在这里我们需要明确,继承存在如下缺陷:

   1)  父类变,子类就必须变

   2)  继承破坏了封装,对于父类而言,它的实现细节对与子类来说都是透明的。

   3)继承是一种强耦合关系

   4)到底要不要使用继承呢?

   根据当前情况,看看是否需要从子类向父类进行向上转型?如果必须向上转型,则继承是必要的,但是如果不需要,则应当好好考虑自己是否需要继承

   三、Java 多态(Polymorphism)

   继承为多态的实现做了准备,在Java中有两种形式可以实现多态:继承和接口

1.   多态存在的三个必要条件
1) 继承
在多态中必须存在有继承关系的子类和父类

2) 重写
子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法

3) 向上转型
父类引用指向子类对象,也就是向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备调用父类的方法和子类的方法
2.  基于继承实现的多态
基于继承的实现机制主要表现在父类和继承该父类的一个或多个子类对某些方法的重写多个子类对同一方法的重写可以表现出不同的行为
3. 基于接口实现的多态
继承是通过重写父类的同一方法的几个不同子类来体现的,那么也可以通过实现接口并覆盖接口中同一方法的几不同的类体现的。
在接口的多态中,指向接口的引用必须是指定这实现了该接口的一个类的实例程序,在运行时,根据对象引用的实际类型来执行对应的方法。
继承都是单继承,只能为一组相关的类提供一致的服务接口。
但是接口可以是多继承多实现,它能够利用一组相关或者不相关的接口进行组合与扩充,
能够对外提供一致的服务接口。所以它相对于继承来说有更好的灵活性。
4. 多态的实现
 1 package wang.isee.polymorphism;
 2 
 3 public class Shape {
 4     public static void main(String[] args) {
 5         // 多态
 6         Circle cir = new Circle();
 7         cir.draw();
 8         Square squ = new Square();
 9         squ.draw();
10         Triangle tri = new Triangle();
11         tri.draw();
12     }
13 
14     public void draw() {
15     }
16 }
17 
18 class Circle extends Shape {
19     public void draw() {
20         System.out.println("Circle.draw()");
21     }
22 }
23 
24 class Square extends Shape {
25     public void draw() {
26         System.out.println("Square.draw()");
27     }
28 }
29 
30 
31 class Triangle extends Shape {
32     public void draw() {
33         System.out.println("Triangle.draw()");
34     }
35 }

    四、总结

    面向对象编程是利用类和对象编程的一种思想。

    万物可归类,类是对于世界事物的高度抽象,不同的事物之间有不同的关系 ,一个类自身与外界的封装关系,一个父类和子类的继承关系, 一个类和多个类的多态关系。万物皆对象,对象是具体的世界事物,面向对象的三大特征:封装,继承,多态。封装说明一个类行为和属性与其他类的关系,低耦合,高内聚继承是父类和子类的关系多态说的是类与类的关系

    

   参考链接:

   https://zhuanlan.zhihu.com/p/93123305

posted @ 2022-12-31 22:50  欢乐豆123  阅读(19)  评论(0编辑  收藏  举报