Java三大特性:封装继承和多态

封装(Encapsulation)

1. definition

封装是指将类的数据或者过程隐藏起来的一个过程。在面向对象程序设计中,一个类以及其行为和属性都应该被视作一个整体,所以是不应该让其他类随意修改的。封装的目的就是将这些属性和方法通过访问域关键字隐藏后,提供一个简单的访问接口给其他类。

public class Person{
    private String name;
    private int age;

    public int getAge(){
      return age;
    }

    public String getName(){
      return name;
    }

    public void setAge(int age){
      this.age = age;
    }

    public void setName(String name){
      this.name = name;
    }
}

2. 为什么不直接把属性设为public,而用getter和setter方法?

如果直接访问,那么任何程序都可以随意更改这个属性的值,即使把他置空或者置为非法值

这里不光是指语法错误,可能是语义错误。比如规定x>0,直接设为了x<=0)。

通过间接访问的方式,可以通过setter方法来对其赋值过程进行一个过滤和加工。虽然通常并没有过滤的这个过程,但是一旦出错,我们可以直接在setter中实现。

另外,getter方法可以决定是返回其真实值还是克隆抑或是其他任意安全的值。

继承(inheritance)

1. definition

继承是面向对象中复用代码的一种手段,一个类可以衍生出子类,而子类通常是在功能或者行为上与父类相似的但却更具体的类。

class 父类 {
}
 
class 子类 extends 父类 {
}

Java中支持多重继承(纵向),但并不能同时继承多个(横向)

final 关键字声明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写

2. 构造方法

当调用子类的构造函数时,子类会(隐式或显式)调用父类的构造函数。

如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。

如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。

class A{
    A(){System.out.println("A");}
    A(int i){System.out.println("A:"+i);}
}
class Aa extends A{
    Aa(int i){}
}

当直接调用new Aa(i)时,会隐式调用super()即A(),这个时候会输出A;而当A不存在第一种构造函数时,则必须在Aa(int i)中显式的调用super(int i)。

隐式的调用一定是无参的构造函数

接口(Interface)和抽象类(Abstract Class)

1. 抽象类

不可以被实例化的一种特殊的类,但是可以被继承。

抽象方法

public abstract class Employee
{
   private String name;
   private String address;
   private int number;
   
   public abstract double computePay();
   
   //其余代码
}

抽象方法就是一个并没有实现的方法,有抽象方法的类一定是一个抽象类,但是抽象类并不一定含有抽象方法

子类如果继承抽象类的话,如果该抽象类中存在抽象方法,那么子类必须实现该抽象方法才能被实例化;否则必须也声明为抽象类。

显然一个没有被实现的方法如果被实例化是不符合逻辑的,因为根本不能调用

2. 接口

接口应该可以被理解为一种行为方式的规范,当实体类需要做某些事的时候,需要按照这些规范去实现,而怎么实现可以不必关心。

interface Animal {
   public void eat();
   public void travel();
}

与抽象类的区别:

  1. 接口中的所有方法必须都是公共的抽象方法。在实现上是隐式的,也就是所有方法前面默认加上了public abstract
  2. 接口中的所有属性都隐式的加上了static final,也就是说是静态不可修改的,同时这种情况下必须在定义的时候就对变量进行初始化。
  3. 一个类可以同时实现多个接口

多态(Polymorphism)

1. definition

多态就是指同一个行为可以通过多种形态进行表现,具体到代码中就是一个方法可以由多种途径实现(重载和重写)。

2. 实现

class A{
    void s() {};
}
class Aa extends A{
    void s() {System.out.println(1111);};
    void s(int i) {System.out.println(i);};
}

Aa中第一种s的实现叫做重写(override)即把父类的代码覆盖了,第二种叫对s()的重载(overload)即重新定义了一种新的名为s的方法的形态。

向上/下 转型

1. 向上转型(从具体到抽象)

向上转型: 用子类的对象去实例化父类,父类可以调用被覆盖的方法

比如

class A {
         public void print() {
                  System.out.println("A:print");
         }
}

class B extends A {
        public void print() {
        System.out.println("B:print");
        }
         
}

public class Test{
         public static void main(String args[])
         {
                  A a = new B();          //通过子类去实例化父类
                  a.print();
         }
}

最终打印的结果是"B:print"

这是因为我们通过子类B去实例化的,所以父类A的print方法已经被子类B的print方法覆盖了。

另外要注意:

向上转型父类引用只能调用父类中原本存在而被子类覆盖的方法,子类单独的方法不可调用

2. 向下转型(从抽象到具体)

父类对象强制转换成子类对象

比如:

class A {
         public void print() {
                  System.out.println("A:print");
         }
}

class B extends A {
         public void print() {        
                  System.out.println("B:print");
         }
         public void funcB(){
                  System.out.println("funcB");
         }
}

class C extends A {
         public void print() {        
                  System.out.println("C:print");
         }
         public void funcC(){
                  System.out.println("funcC");
         }
}

public class Test{
         public static void func(A a)
         {
                  a.print();
                  if(a instanceof B)
                  {
                          B b = (B)a;   //向下转型,通过父类实例化子类
                          b.funcB();    //调用B类独有的方法
                  }
                  else if(a instanceof C)
                  {
                          C c = (C)a;  //向下转型,通过父类实例化子类
                          c.funcC();   //调用C类独有的方法
                  }
         }

         public static void main(String args[])
         {
                  func(new A());   
                  func(new B());
                  func(new C());
         }
}

很容易想到结果,这里就不给出了

通过向下转型可以单独调用子类其特有的方法

3. 结论

向上向下转型的好处在于编写函数的时候,只需将父类(接口)定义为参数即可,因为所有子类都可以看成是特殊的父类;而向下转型感觉一般用的比较少

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容