天呐,你还记得java特性:封装、继承、多态,是个啥吗

前言

首先看到这个标题,大家可能觉得很无聊,这三个词可以说基本上随便一搜,就一大堆文章解释的头头是道,但是即便如此,我为啥还是要写这篇文章呢,是因为今天在给大家准备后续内容时,无意看到了这三个词,然后顺带想了一下各自的含义,发现封装和继承还比较好理解,结果另外一个多态琢磨了半天,竟然一时忘了这个词的含义,突然有点愕然,自己才工作了一年,居然很多基础概念都快记不清了,oh,太可怕了!于是才有了这篇文章,一方面提醒自己,一方面也分享出来给大家,让大家也不能忘记哦。

正文

1、封装

封装在这三个词里面是最容易理解的,专业术语我就不多说了,因为说了你们也记不住,我也记不住,在我看来,最容易理解的方法就是举例,OK,那我们就举个例子,比如现在我希望有一个类,这个类有一些属性和功能,并且可以完成一些,比如

  • 有眼睛,属性
  • 有嘴巴,属性
  • 可以吃饭,功能
  • 可以睡觉,功能
  • 心上人,属性
  • ······

属性就相当于是这个类拥有的成员变量,这个变量的值就对应具体的属性,比如眼睛,有单眼皮、双眼皮,这个很好理解。功能就相当于是这个类拥有的方法,比如吃饭、睡觉,都是在执行某个动作,也就是类的某个方法的执行。然后还有一些访问权限控制,比如心上人这个属性,这个类可能不希望其它对象知道,所以这个属性就是私有的,也就相当于java里的private访问权限。

通过上面说的一些要素,成员变量、方法、访问控制等,我们就可以拼凑出一个简单的类来了,不用我说,大家应该也知道了这个类就是:可爱的你。而定义这些要素以及拼凑的过程就是封装

现在我们明白了封装的意思,但是这样做可以带来哪些好处呢,为啥无缘无故要封装这个封装那个的,这是因为封装后,这个类对象,外界只会知道它暴露出来的属性或者方法,此外,对于方法,外界只知道该类对象有这个方法,比如可以吃饭,但是并不知道该方法的细节,比如吃的什么、在哪里吃的等这些细节。那隐藏这些细节或者属性有啥用呢,藏着掖着的有啥好处吗,当然是有好处的,比如吃饭这个方法,里面需要用到筷子这个属性,但是假设由于我没有隐藏筷子这个属性,导致该属性被外界修改了,现在只有一只筷子了,所以这饭也没法吃了,最终吃饭失败。

2、继承

这个词也比较简单,很好理解,同样的方法,我们还是通过举例来简单说明一下,比如现在想吃点水果,但是不知道吃什么,平常吃的比较多的可能就是苹果、香蕉、橘子、荔枝等,一番纠结后选择了口感最好的荔枝。OK,在这个场景下,就可以抽取一个典型的继承模型出来,对于水果,可以理解为它有一个属性:可以被吃。对于苹果、香蕉、橘子、荔枝,它们也和水果一样,有一个同样的属性:可以被吃,但是它们除了这个属性之外,还拥有一些不同的属性,比如苹果是青色,香蕉是黄色、橘子是橙色、荔枝是深红色等,这些属性是水果这个对象所没有的,所以我们可以将特有的属性定义在苹果、香蕉、橘子、荔枝中,对于公共的属性:可以被吃,我们选择去继承水果这个对象,来让苹果、香蕉、橘子、荔枝通过继承的方式获取属性:可以被吃。这就是继承

那说了半天,好像确实明白了继承的意思,那这样做的意义何在呢,意义就在于对于一些有公共属性的对象,无需重复在各自内部定义属性,只需要定义一个父类对象,然后在父类对象里定义这些公共属性,然后其它的类就只需要负责各自特有的属性定义,公共的属性通过继承的方式一次搞定。

3、多态

这个词相对前两个,看上去就感觉高级一点,也没那么容易一下子就理解,但是如果扩展为:多种形态,这样的描述方式是不是就容易理解一点,那再扩展一下描述:一个类可能存在多种形态,是不是又清晰了一点,好像就是在说父子类的关系,所以这里不难想到上面说的继承,但是它既然作为一个单独的词,肯定有另外的意义所在,要理解这个词的含义,我还是一样的方法,举个例子,但是不是中文描述,虽然中文描述可以说清,但是不好理解,所以我就直接举一行代码:

Person person = new ZhangSan();

Person是一个父类,里面有一个方法eat()代表吃米饭,ZhangSanPerson的一个子类,它重写了父类的方法eat()代表吃披萨,并且还有一个单独的方法swim()代表游泳。它们的定义如下

class Person{
	public void eat(){
    System.out.println("吃米饭");
  }
}
class ZhangSan extend Person{
  @Override
	public void eat(){
    System.out.println("吃披萨");
  }
  
  public void swim(){
    System.out.println("我会游泳");
  }
}

这种情况下,我们如果调用例子中的person.eat(),会出现什么样的情况呢,通过运行,我们发现了最终结果是:吃披萨,而这个结果就是多态的一种体现,因为我们在声明的时候,明明只是声明了一个父类对象,结果却调用到了子类的方法,原因就是因为我们是用子类来初始化的,如果子类重写了父类的方法,那用子类初始化的父类对象就会调用子类的实现方法,emmmmm,这句话可能有点绕,总之不理解的时候,想想上面的例子就明白了。

在上面的例子中,如果再来一个对象LiSi或者WangWu,也分别继承Person,并重写eat()方法,以及添加各自的特性方法,那么Person person = new ZhangSan();Person person = new Lisi();Person person = new WangWu();,以及类似这样的代码,就可以理解为Person这个类能以ZhangSan Lisi WangWu这三种形式存在,也就是我们上面说的,一个类存在多种形态,也就是多态,怎么样,明白了吗。

OK,现在我们明白了多态是什么,那这样设计的意义何在呢,好像只是给人感觉很绕,但是没有什么用武之地,其实之所以这样想,还是因为对平常的代码没有仔细观察和思考,当然你可能也已经正在用这个特性来开发代码,只不过你不知道这个特性叫多态而已,在实际开发中,接口和抽象类其实就是多态最为直接的一种使用体现,举个很简单的例子,比如:张三现在需要回家,一般是滴滴打车回家。在这样一个简单的场景中,我们定义一个类ZhangSan,添加一个方法goHome去执行这个回家的操作,回家过程中需要选择一种交通方式才能回家,我们默认是滴滴打车回家,所以最终定义如下:

class ZhangSan{
  TrafficWay trafficWay = new DiDi();
	void goHome(){
    trafficWay.go();
  }
  
  void setTrafficWay(TrafficWay way){
    trafficWay = way;
  }
}
interface TrafficWay{
  void go();
}
class DiDi implements TrafficWay{
  void go{
    System.out.println("滴滴打车回家");
  }
}

但是有一天加班太晚打不到车了,没办法ZhangSan这次只能坐地铁回家,这时我们只需新增一个TrafficWay接口的实现类,再给ZhangSan设置进去即可,

class SubWay implements TrafficWay{
  void go{
    System.out.println("坐地铁回家");
  }
}
ZhangSan zs = new ZhangSan();
zs.setTrafficWay(new SubWay());
zs.goHome();

同样的,假设地铁也停运了,那ZhangSan只能走路回家了,我们同样的也只需要新增一个TrafficWay接口的实现类Walk,而无需修改以前的代码,就达到了效果。在该例子中,相信也不用我多说了吧,TrafficWay这个接口就是一个多态的体现,能以DiDiSubWayWalk等各种形态存在,用来满足不同情形的需求。

这就是多态的实际应用场景。怎么样,明白了吗,是不是发现原来我们平常看到的这些设计方式,原来就是多态的一种思想,这种思想一般用在框架设计上面,哪一天我们需要设计一个框架,就可以用这个思想啦。

结语

最后,我想感叹下,虽然这三个词在我们最初学java的时候,就会去了解学习,但是我们从java使用到现在,真真正正理解并且将这些特性思想融入到实际开发中的,又有多少呢,有时候我们只是沉浸于各种业务开发,而忽略了一些优秀的设计思路或方法,好了,今天就到这吧,本篇应该只算是一个java基础知识的复习,后续内容尽请期待哦,下次见!!!

=========================================
另外,本文章也会同步发布在本人的公众号上面哦,欢迎关注呀,公众号里会优先推送最新的文章,还有各种送书等福利,以及各种小惊喜,怎么样,快来关注呀!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章