封装继承和多态

封装继承和多态

一、封装

是什么:

首先是抽象,把事物抽象成一个类,其次才是封装。对外表示为一个对象,隐藏对象的属性和动作实现的细节,仅对外公开接口。

为什么:

对外简化编程。高内聚低耦合使用者不需要了解具体的实现细节,而是要通过外部接口,一特定的访问权限来使用类的成员(包括成员函数和成员变量)。对内保护数据安全,使用者不可随意修改属性值。此外,封装符合面向对象设计原则的第一条:单一性原则,一个类把自己该做的事情封装起来,当内部的逻辑发生改变时,外部调用不用因此而修改。

怎么做:

基本要求是把所有的成员变量(对象的属性)私有化。对每个属性提供get和set方法。

补充:

与C++相比,Java的封装更彻底(C++向后兼容C,而C是面向过程的程序设计,所以C++允许把函数和变量写在类外,而java不允许)。Java成员函数的实现是直接写在class里面的(不管这个成员函数的实现有多复杂),而C++是在class里面写简短的函数声明,然后在class外面写函数具体的实现。当然C++也可以在类内实现,只是当时老师上课要求统一写在外面。在class里只写声明,在类外通过作用域符::写实现。
程序员封装类的好坏的评定标准:职责单一、扩展性、执行结果是否清晰;简言之,封装就是无需暴露细节,暴露该暴露的,隐藏该隐藏的,让任意两者之间的耦合恰当。(eg.买车只需要会开即可,不需要关注引擎、发动机等工作细节)

二、继承

是什么:

当两个类具有相同的特征(属性,比如售票员和乘客都是“人”)和行为(方法,比如售票员和乘客都要吃饭和睡觉)时,可以将相同的部分抽取出来放到一个类中作为父类(上面的例子中,“人”就是父类),其他两个类继承这个父类。继承后子类自动拥有了父类的属性和方法,目的是实现功能的扩展,子类也可以复写父类的方法,即方法的重写(这里穿插着多态的内容)。子类不能访问父类中访问权限为private的成员变量和方法。子类可以重写父类的方法,即命名与父类同名的成员变量。

为什么:

继承可以重复使用代码,降低冗余。代码重用是一点,最重要的一点是可以向上转型(将导出类看为它的基类的过程),这是Java面向对象最重要的特性——多态的基础。

怎么做:

子类继承父类所有,只是访问受约束。通过关键字extends继承。

补充:

java类可以分为三类

1.类:使用class定义,没有抽象方法

2.抽象类(不能被实例化 比如“水果”是一个抽象类,但无法实例化它,拿不出一个具体的东西):只能被继承用abstract class定义

3.接口(对抽象类进一步的抽象,比如飞机和鸟都会飞 “飞”就可以被设计成一个接口):使用interface定义,只能有抽象方法,所有的属性都是static final来定义的。
简单地说就是为了代码复用,为多态提供基础。

三、多态

是什么:

首先要知道方法的唯一性标识是方法名和参数(参数个数 类型 顺序)。同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果,这就是多态性。

多态可以说是“一个接口,多种实现”或者说是父类的引用变量可以指向子类的实例,被引用对象的类型决定调用谁的方法。

为什么:

程序的可扩展性及可维护性增强。这里我觉得可以类比于C++中的模板类来理解,针对用户输入参数的个数和类型来执行相应的操作。我看其他论坛上也有观点是多态为了接口重用(以我现在的理解来看,就是子类可以复用父类的方法)。

怎么做:

首先java实现多态需要有三个条件:继承(在多态中必须存在有继承关系的子类和父类)、重写(子类对父类的某些方法进行重新定义,在调用这些方法时就会调用子类的方法)、向上转型。

具备以上的前提条件后,实现多态的方法(C++中实现多态的方法有函数重写…重写是指子类重新定义父类虚函数的方法…与重载…指允许存在多个同名函数,而这些函数的参数列表不同 …)有编译时多态(方法的重载)和运行时多态(继承时方法的重写)。

编译时多态很好理解,就是编译器在编译的时候会根据函数不同的参数表,对同名函数的不同名称做不同的修饰,这些同名函数就成了不同的函数。也正是因为这一点,师兄说函数重载不算多态。

运行时多态依赖于继承、重写和向上转型(简单的理解为,导出类可以看成它的基类)。基于继承实现多态:
public class Toilet{

public void toilet(){

    system.out.print("厕所")

    }

}

public class M extend Toilet{

public void toilet(){

     system.out.print("男厕")

    }

}

public class W extend Toilet{

public void toilet(){

    system.out.print("女厕")
    
    }

}

class A {

public static void main(String[] args){
    Toilet mToilet = new M();    //父类引用指向子类对象

    Toilet wToilet = new W();    //父类引用指向子类对象

    mToilet.toilet();            //执行M的toilet()方法

    wToilet.toilet();            //执行W的toilet()方法 

    }

} 

程序执行结果: 男厕女厕
代码链接:https://www.jianshu.com/p/1d6219ad43a1
代码来源:简书

基于接口实现多态:

public interface Toilet{

public void toilet();

}

//接口实现类

public class M implement Toilet{

 public void toilet(){ system.out.print("男厕")

}

}

//接口实现类

public class W implement Toilet{

public void toilet(){

    system.out.print("女厕")

    }

}

class A{

public void static main(String[] args){

    Toilet mToilet = new M(); //接口引用变量指向接口实现类对象

    Toilet wToilet = newW(); //接口引用变量指向接口实现类对象

    mToilet.toilet(); 

    wToilet.toilet();

    }

}

程序执行结果: 男厕女厕
代码链接:https://www.jianshu.com/p/1d6219ad43a1
代码来源:简书

很棒的例子:
class Human {
public void fun1() {

    System.out.println("Human fun1");
    fun2();
}
public void fun2() {
    System.out.println("Human fun2");
   }
}
class Programmer extends Human { //函数的重载
public void fun1(String name) {
    System.out.println("Programmer's fun1");
}

//函数的重写

public void fun2() {
    System.out.println("Programmer's fun2");
}
}

public class Test {

public static void main(String[] args) {
    Human human = new Programmer();//出现“类型不匹配时”,判断口诀:变量多态看左边,方法多态看右边,静态多态看左边
    human.fun1();//没有对应的fun1()函数所以向上转型human类型,执行human中的fun1()函数。而funl()中含有fun2(),而此函数在子类中被重写了,所以执行子类的fun2();    } /*
 * Output:
 *  Human fun1
 *  Programmer's fun2
 */
 }
补充:

跳出多态的细节,从整体上看多态就是一种表现形式有多种结果呈现。
这三个思想是设计模式的基础,也是整个Java的基础,值得学而时习之。
在这里插入图片描述

点个关注,不迷路

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值