Java 三大特性:继承,多态和封装
(一)继承
1.类的继承格式:在 Java 中通过 extends 关键字可以申明一个类是从另外一个类继承而来的(extends 只能继承一个类),一般形式如下:
class 父类 {
}
class 子类 extends 父类 {
}
2.继承的特性
- 子类拥有父类非private的属性,方法。可以通过直接访问name(eat();)或super.name(super.eat())来访问父类属性和方法。(直接访问时注意父类和子类是否有相同的方法名,有则用super.方法名() )
- 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
- 子类可以用自己的方式实现父类的方法。
- Java的继承是单继承,但是可以多重继承(传递性),单继承就是一个子类只能继承一个父类,多重继承就是,例如A类继承B类,B类继承C类,所以按照关系就是C类是B类的父类,B类是A类的父类。
提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系)。
使用 implements
关键字可以变相的使java具有多重实现的特性,使用范围为类实现接口的情况,可以同时实现多个接口(接口跟接口之间采用逗号分隔)
eg:
/*Interface A*/
public interface A{
public void eat();
public void sleep();
}
/*Interface B*/
public interface B{
public void haha();
}
class C implements A,B{
public void eat(){...}
public void sleep(){...}
public void haha(){...}
}
*注:所有的类都是继承于java.lang.Object,当一个类没有继承的两个关键字(extends,implements),则默认继承object(这个类在 java.lang 包中,所以不需要 import)祖先类。
3.继承关键字:extends, implements, super, this, final;
- final 关键字声明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写:
/*声明类*/
final class 类名{//类体}
/*声明方法*/
[可视度] final 返回值类型 方法名{//方法体}
4.构造器
- 子类不能继承父类的构造器(构造方法或者构造函数),但是父类的构造器带有参数的,则必须在子类的构造器中显式地通过super关键字调用父类的构造器并配以适当的参数列表。
- 如果父类有无参构造器,则在子类的构造器中用super调用父类构造器不是必须的,如果没有使用super关键字,系统会自动调用父类的无参构造器。
class SuperClass {
private int n; //the private attribute n can not be inherited
SuperClass(){
System.out.println("SuperClass()");
}
SuperClass(int n) {
System.out.println("SuperClass(int n)");
this.n = n;
}
}
class SubClass extends SuperClass{
private int n;
SubClass(){
super(300); //if without super(300),it will inherit the SuperClass() rather then SuperClass(int n)
System.out.println("SubClass");
}
public SubClass(int n){
System.out.println("SubClass(int n):"+n);
this.n = n;
}
}
public class Test_2{
public static void main (String args[]){
SubClass sc = new SubClass();
SubClass sc2 = new SubClass(200);
}
}
/*输出结果*/
SuperClass(int n)
SubClass
SuperClass()
SubClass(int n):200
5、类关系继承中的子类对象继承父类和父类对象调用子类方法:
- 若定义某对象为父类对象的子类声明(如:Employee e=new Salary() ; ),则想要调用子类中的方法的前提是:父类中必须声明和子类方法类型和参数均相同的方法(方法体可以不同),或即重写
/*假设Salary中有方法 getName(),而Employee中没有该方法,则以下执行语句将出现编译错误*/
Employee e=new Salary();
e.getName();
/*假设Salary中有方法 getName(),而Employee中也有该方法,则以下执行语句将正常执行*/
Employee e=new Salary();
e.getName();
- 若定义某对象为子类对象,则其继承父类的方法是不需要重写父类中的方法,直接通过super调用既可
/*
class Salary{
...
public void getSuperName(){
super.getName(); //getName() is a function of father class Employee
}
}
*/
Salary s=new Salary();
s.getSuperName();
(二)、多态
1、多态表述图:
2、多态存在的三个必要条件
- 继承
- 重写
- 父类引用指向子类对象,比如:
Parent p = new Child();
3、多态例子解析:
public class Test {
public static void main(String[] args) {
show(new cat()); //实例化cat类
show(new dog()); ////实例化dog类
Animal a=new cat(); //向上转型为Animal
a.eat(); //通过判断Animal中是否有eat()方法决定是否能调用cat中的eat()方法
cat c=(cat)a; //向下转型,将a下转为cat类实现
c.work(); //Animal中无需work()方法即可实现此调用
}
public static void show(Animal a) { //该方法必须定义为 static 才能被主函数调用
a.eat();
//类型判断
if(a instanceof cat) {
cat c=(cat)a;
c.work();
}
else if(a instanceof dog) {
dog d=(dog)a;
d.work();
}
}
}
//the abstract class of Animal
abstract class Animal{
abstract void eat();
}
//the class of cat
class cat extends Animal{
public void eat() {
System.out.println("eat fish");
}
public void work() {
System.out.println("catch mouse");
}
}
//the class of dog
class dog extends Animal{
public void eat() {
System.out.println("eat meat");
}
public void work() {
System.out.println("look the house");
}
}
instanceof的用法:
instanceof 是Java保留的关键字,它的功能是判断其左边对象是否为其右边类的实例,返回的是boolean类型的数据。用它来判断某个对象是否是某个Class类的实例。
*用法:
boolean result = object instanceof class
4、多态的几种实现方式:
- 重写
- 接口:体现在接口的不同实现。
- 抽象类与抽象方法:体现在抽象类的继承和抽象方法的重写。
(三)、Java 封装
1、定义:
在面向对象程序设计方法中,封装(英语:Encapsulation)是指一种将抽象性函数接口的实现细节部份包装、隐藏起来的方法。封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。要访问该类的代码和数据,必须通过严格的接口控制。
2、实现Java 封装的步骤
- 修改属性的可见性来限制对属性的访问(一般限制为private),如:
public class Person {
private static String name;
private static int age;
public static void main(String[] args) {
System.out.println(Person.name);
System.out.println(age);
}
} //除了类本身,其他类都访问不了name,age属性
- 对每个值属性提供对外的公共方法访问,也就是创建一对赋取值方法,用于对私有属性的访问,如:
/*Person.java:*/
public class Person{
private String name;
private int age;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
}
/*Test.java:*/
public class Test {
public static void main(String[] args) {
Person p=new Person();
p.setName("lhx");
System.out.println("Your name is: "+p.getName());
}
}