java 三大基本特征:继承、 封装、多态
继承是java中对类之间关系的描述,如果多个类同时拥有相同的属性、行为就可以将其抽取成为基类, 然后子类分别继承于它,例如狗,猫,鸭子都有名字, 脚数量等属性,同时也有会吃,会叫等行为,所以可以将这些属性行为都抽取为动物类,至于它们行为的差异性可以通过继承后重写基类的方法实现。 其实java中的向上转型, 多态都是基于继承的。
所谓向上转型就是让基类的引用指向子类的引用,其实这也就是上边所说的用来描述类之间的关系,因为可以说子类是基类(狗是动物),而在多数情况下, 使用继承的原因也是为了提供这样的一个关系。
2.封装就是打包、包装、数据隐藏的意思,也就是将某个事物的属性,行为封装到一个类中, 然后将这些东西隐藏,同时提供一下让人知道它们拥有这些行为的接口, 如:我们知道狗会吃东西,会叫,但是它们吃东西然后消化、叫时时怎么发出声音这些细节我们不需要知道。
使用封装有三大好处:
1、良好的封装能够减少耦合。
2、类内部的结构可以自由修改。
3、可以对成员进行更精确的控制。
4、隐藏信息,实现细节。
3.多态就是一个类的引用在不同的状态下回呈现出不同的状态, 看代码:
package com.mjlf.myBatis.accessControl.animal;
/**
* Created by a123 on 16/12/11.
*/
public class Animal {
public void eat(){
System.out.println("animal eat");
}
public void cry(){
System.out.println("animal cry");
}
public static void main(String[] args){
Animal animal = new Animal();
Animal animal1 = new Dog();//向上转型,用基类的引用指向子类的引用
Animal animal2 = new Cat();
animal.cry();
animal1.cry();
animal2.cry();
}
}
class Dog extends Animal{
public void eat(){
System.out.println("dog eat");
}
public void cry(){
System.out.println("dog cry");
}
}
class Cat extends Animal{
public void eat(){
System.out.println("cat eat");
}
public void cry(){
System.out.println("cat cry");
}
}
/**
animal cry
dog cry
cat cry
从输出结果可以发现, 同样是Animal类的对象,同样是调用cry()方法,但是输出的接口去完全不一样, 这就是多态。
*/
注意:
1. 子类只能继承基类共有或protected的属性和方法, 在使用多态的时候要注意这一点,见下例:
package com.mjlf.myBatis.accessControl.animal;
/**
* Created by a123 on 16/12/11.
*/
public class Animal {
private void owns(){
System.out.println("myself function");
}
public static void main(String[] args){
Animal animal = new Animal();
Animal animal1 = new Dog();
Animal animal2 = new Cat();
animal.owns();
animal1.owns();
animal2.owns();
}
}
class Dog extends Animal{
private void owns(){
System.out.println("dog function");
}
}
class Cat extends Animal{
private void owns(){
System.out.println("cat function");
}
}
/**
myself function
myself function
myself function
根据上一例所说, 这里应该输出的是
myself function
dog function
cat function
但是却不是,所以可以发现子类不能继承基类的private 方法,当然属性也是如此。
*/
如果是默认权限修饰, 是否可以被继承呢?
//同步实验
package com.mjlf.myBatis.accessControl.animal;
/**
* Created by a123 on 16/12/11.
*/
public class Animal {
void owns(){
System.out.println("myself function");
}
public static void main(String[] args){
Animal animal = new Animal();
Animal animal1 = new Dog();
Animal animal2 = new Cat();
animal.owns();
animal1.owns();
animal2.owns();
}
}
class Dog extends Animal{
void owns(){
System.out.println("dog function");
}
}
class Cat extends Animal{
void owns(){
System.out.println("cat function");
}
}
/**
myself function
dog function
cat function
*/
//不同包中实验
package com.mjlf.myBatis.accessControl.entity;
import com.mjlf.myBatis.accessControl.animal.Animal;
public class Cat extends Animal {
void owns(){
System.out.println("cat function");
}
}
package com.mjlf.myBatis.accessControl.entity;
import com.mjlf.myBatis.accessControl.animal.Animal;
public class Dog extends Animal {
void owns(){
System.out.println("dog function");
}
}
package com.mjlf.myBatis.accessControl.animal;
import com.mjlf.myBatis.accessControl.entity.Cat;
import com.mjlf.myBatis.accessControl.entity.Dog;
/**
* Created by a123 on 16/12/11.
*/
public class Animal {
void owns(){
System.out.println("myself function");
}
public static void main(String[] args){
Animal animal = new Animal();
Animal animal1 = new Dog();
Animal animal2 = new Cat();
animal.owns();
animal1.owns();
animal2.owns();
}
}
/*
myself function
myself function
myself function
根据上述两个实验可以知道,在同一包中,默认权限修饰的方法是可以被重写的,但是在不同包中就不能被重写
*/
2.继承中不能继承基类静态方法, 同时也要注意继承中的属性的使用, 否则会出现意想不到的结果
package com.mjlf.myBatis.accessControl.animal;
/**
* Created by a123 on 16/12/11.
*/
public class Super {
public int field = 0;
public int getField() {
return field;
}
public static void main(String[] args){
Super sup = new Sub();
System.out.println("sup.field : " + sup.field + " sup.getField() :" + sup.getField());
Sub sub = new Sub();
System.out.println("sub.field : " + sub.field + " sub.getField() :" + sub.getField() +
" sub.getSuperField() :" +sub.getSuperField());
}
}
class Sub extends Super{
public int field = 1;
public int getField() {
return field;
}
public int getSuperField(){
return super.getField();
}
}
/*
sup.field : 0 sup.getField() :1
sub.field : 1 sub.getField() :1 sub.getSuperField() :0
可以发现调用sup.field是值为0, 说明是Super类的field属性,也就是在基类和子类中同时拥有相同的是属性时,通过基类对象.属性名调用的是基类的属性, 不会出现多态效果, 但是如果调用其属性的get方法,则得到子类对象该属性的值, 因为在这里出现多态效果,在使用时必须注意这一点,如果在子类对象中想获取基类对象中的该属性的值, 可以通过super对象调用,在继承关系中,super表示子类对象的上一级基类对象
*/
上述情况需要注意,但是最后一种情况一般不会出现,在实际开发过程中很少有人会将在子类中取名属性和基类完全相同,即使相同, 在封装中我们也说道,一般所有的属性都是对外隐藏的。