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

时间:2022-05-31 23:11:33
总述


实习小半年,回顾自己的代码,大体思路是有但在具体实现上愈发感觉混乱,自觉是基础不牢固的原因,于是继续看Java编程思想,遇到重要的地方就做一些总结。

这一篇总结Java三大特性:继承、封装和多态。



继承


1.使用场景

分析两者关系,若为IS—A型,就应使用继承。

比如,猫是动物的一种,它理应拥有动物最基本的属性和功能,所以构造Cat类时就可以继承已有的Animal类,在其基础上做扩展。Cat类就称为子类,Animal类就称为父类。


2.特点

继承很方便的实现了代码复用,子类可以直接获得父类的已有功能,不需自己实现,然后再扩展自己独有的功能就好,效率提高。

但这是一种强耦合关系,因为父类的实现是对子类透明的,父类变动则所有子类均受变动,而且Java有单继承限制,一个类只能有一个父类,哪怕它与很多类有IS—A关系。


3.子类真正继承了什么?

一个类中的内容可大致分成三部分:属性,方法和构造器。就从这三方面分析子类真正继承了什么。

属性和方法:只要是非private型的,不论是否静态或其他,均可由子类继承使用。当然子类可以对已继承的属性和方法进行覆盖,换成自己的实现。
构造器:构造器只能调用,不可继承。Java有构造方法链,编译器会从父类的构造方法开始向子类一级一级完成构建,这是必须的,对父类构造方法的调用一定是子类构造方法中的第一行代码。当然,若父类有默认的空参构造器,编译器会默认调用不需我们手动调用,但若父类没有,则必须手动调用:super(XXX)
.


4.要牢记的几点

IS—A型关系下才应使用继承;子类继承到的是父类非private的属性和方法;子类可以*扩展,添加自己的属性和方法;子类可以覆盖继承到的属性和方法,换成自己想要的实现


封装


1.使用场景

对象有自己的属性和方法,当我们需要对这些信息加以保护或限制外界的访问权限时,就要使用封装。

比如,对一些重要实现逻辑客户不能更改也不必知道,就可使用private修饰符,对一些重要属性客户只能读不能写,就可使用private修饰符外加get方法。


2.优势
减少相互间的依赖,降低耦合,容易维护和使用;内部逻辑更改迭代不会影响客户的使用;控制了客户权限,安全性提高。


3.四种修饰符

在控制客户访问权限时,最常用的是四种修饰符,访问权限由大到小为:
public>protected>void>private
其中,public型无限制,protected型限制为子类或包内可访问,void型限制包内可访问,private型限制仅类中可访问


多态


1.什么是多态

以子类Cat类与父类Animal类为例,以下写法是正确的:
Animal a=new Cat();
一个变量一般有声明类型和实际类型两种属性,如上代码,变量a的声明类型为Animal,实际类型为Cat,这是多态的一部分体现。
所谓多态,是指变量的实际类型及变量最终会调用何处的实现(属性和方法等)只有在运行期间才确定,编译时并不确定。正因为运行时才确定,所以无需更改逻辑代码,运行状态(可以理解为run起来的代码)就会随变量实际类型的改变而改变,这就是多态性。
举个简单例子:
public void runEat(Animal a){
      a.eat();
}
上面的方法,传入Cat型参数,运行时执行的就是Cat类中eat方法,传入Dog型参数,就会执行Dog类中的eat方法了。


2.编译和运行时的具体调用

举个简单例子:

Animal a=new Cat();
a.eat();

如上,若eat方法只存在于Animal类,没有问题,最后调用的就是Animal类中的eat方法;若只存在于Cat类,则会报错,因为向上转型后,a无法直接调用子类中的方法,编译失败,必须先进行类型强转后才可;那若Animal类和Cat类中均有eat方法呢,调用的是Animal类还是Cat类中的呢?编译和运行时一样吗?调用属性时又是什么情况?

直接进行代码测试,如下:

Animal类:

package com.example.shuqiao.helloworld.Data;

/**
* Created by shuqiao on 16/2/18.
*/
public class Animal {
public String value1 = "animal_value1";//非静态数据
public static String value2 = "animal_value2";//静态数据

//非静态方法
public String show(Animal obj) {
return "animal_show_animal";
}

//静态方法
public static String staticShow(Animal obj) {
return "animal_static_show_animal";
}
}

 

 

Cat类:

package com.example.shuqiao.helloworld.Data;

/**
* Created by shuqiao on 16/2/18.
*/
public class Cat extends Animal {
public String value1 = "cat_value1";//非静态数据
public static String value2 = "cat_value2";//静态数据


//非静态方法
public String show(Animal obj) {
return "cat_show_animal";
}

//静态方法
public static String staticShow(Animal obj) {
return "cat_static_show_animal";
}
  }
 
 
 

主Activity:

package com.example.shuqiao.helloworld.Activity;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

import com.example.shuqiao.helloworld.Data.Animal;
import com.example.shuqiao.helloworld.Data.Cat;
import com.example.shuqiao.helloworld.R;


public class MainActivity extends Activity {
public TextView tvShow;//用来展示测试结果

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);//xml中只有一个TextView控件,就不贴了
tvShow = (TextView) findViewById(R.id.tv_show);
test();
}

private void test() {
StringBuilder stringBuilder = new StringBuilder();

Cat cat = new Cat();//声明类型与实际类型一致
Animal animalCat = new Cat();//声明类型与实际类型不一致

//属性
stringBuilder.append("非静态数据:" + "\n");
stringBuilder.append("cat:" + cat.value1 + "\n");
stringBuilder.append("animalCat:" + animalCat.value1 + "\n");
stringBuilder.append("静态数据:" + "\n");
stringBuilder.append("cat:" + cat.value2 + "\n");
stringBuilder.append("animalCat:" + animalCat.value2 + "\n");
stringBuilder.append("\n");

//方法
stringBuilder.append("非静态方法:" + "\n");
stringBuilder.append("cat:"+ cat.show(animal) + "\n");
stringBuilder.append("animalCat:"+ animalCat.show(animal) + "\n");
stringBuilder.append("静态方法:" + "\n");
stringBuilder.append("cat:" + cat.staticShow(animal) + "\n");
stringBuilder.append("animalCat:" + animalCat.staticShow(animal) + "\n");

tvShow.setText(stringBuilder.toString());
}


}


运行结果如下:

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

由上述测试,可知:

不论声明类型与实际类型是否一致,对属性来说:编译检测和运行调用均看声明类型,无论静态与否;对方法来说:则要区分静态与否,静态下编译检测和运行调用均看声明类型,非静态下编译检测看声明类型,运行调用看实际类型。

总结:属性+静态方法,均看左边;非静态方法,编译看左边,运行用右边


3.实现形式

Java中有两种形式可以实现多态:继承和接口。
继承代表IS—A型关系,接口代表HAS—A型关系。比如,新陈代谢这个功能,猫有,树木也有,他们与新陈代谢之间就是典型的HAS—A型关系,所以就应该用接口实现。相对于继承,接口可以多实现,就是说一个类只能继承一个父类但可以实现多个接口,这样就有更灵活的扩充性和组合性。
不过两者形式下的多态均遵从上面2中总结的结论



最后

会继续抽时间总结Java编程思想的,要把重要的基础整理一遍~

有了一点感悟:理论知识不仅要牢,更得会潜移默化的用到实践中~





参考

http://blog.csdn.net/foreverhuylee/article/details/21278311

http://www.cnblogs.com/chenssy/p/3372798.html