java 学习笔记——类之间的关系之封装、继承与多态的详解

封装

一个封装的简单例子

封装就是把对象的属性(状态)和方法(行为)结合在一起,并尽可能隐蔽对象的内部细节,成为一个不可分割的独立单位(即对象),对外形成一个边界,只保留有限的对外接口使之与外部发生联系。
封装的原则:使对象以外的部分不能随意存取对象的内部数据,从而有效的避免了外部错误对它的“交叉感染”。数据隐藏特性提升了系统安全性,使软件错误能够局部化,减少查错和排错的难度。如:微波炉,将线路板(属性)封装在微波炉内部,使用者无法接触到,而通过面板按钮(方法)简单的操控线路板工作。

设计一个CBox类,具有length、width和height三个属性,对每个属性都提供相应的get和set方法,提供构造函数,完成CBox信息的初始化,增加volume()方法,用来计算CBox对象的体积,定义surfaceArea()方法用来计算CBox的表面积。
面向对象的三个特征:


package ch01;

public class test
{
    private int height;
    private int length;
    private int width;

    public int getHeight() {
        return height;
    }
    public void setHeight(int height) {
        this.height = height;
    }
    public int getLength() {
        return length;
    }
    public void setLength(int length) {
        this.length = length;
    }
    public int getWidth() {
        return width;
    }
    public void setWidth(int width) {
        this.width = width;
    }

    public test(int height, int length, int width)
    {
        this.height = height;
        this.length = length;
        this.width = width;
    }

    public int volume()
    {
        return length * width * height;

    }
    public int Area()
    {
        return 2* (length*width+length*height+width*height);

    }
    public static void main(String[] args) {
        test cb = new test(10,20,30);
        int x = cb.volume();
        int y = cb.Area();
        System.out.println(x);
        System.out.println(y);
    }

}

对于代码中快速生成的getsetpublic test(int height, int length, int width)这样的初始化,在eclipse 中都会有快捷的方法,可以在任意一个光标闪烁出单机右键,找到source然后就有了,不要问是什么0·0,因为单词太长了,不想写......

继承

继承是软件重用的一种形式,它通过重用现有类的属性和方法,并增加新功能或修改现有功能来构建新的类。如:“人”这个类抽象了这个群体的一般特性,“学生”和“老师”都具备“人”所定义的一般性,但其各自又有各自的特殊性,在保持了一般性和特殊性的情况下,作为一个新类而存在。

  • 表现的是一种共性和特性的关系,一个类可以继承另一个类,并在此基础上添加自己特有功能,这称为继承。在java中使用extends关键字表现继承关系。

格式:

[访问符][修饰符] class <子类名> extends <父类名>{
  [属性]  //成员变量
  [方法]  //成员
}
public tiger extends animal{
}

下面通过一个简单的例子进行说明

教师和学生类的属性列表

教师类(Teacher) 学生类(Student)
姓名 name 姓名
年龄 age 年龄
性别 gender 性别
工资 salary 成绩
所属院系 department 年级

从上图分析可以看出,教师类和学生类在姓名、年龄、性别上存在共同性,而教师类有两个属性工资和所属院系区别学生类的成绩和年级。

程序实现

父类person

package com.wfu.ch04;

public class Person {
    private String name;//进行封装处理
    private int age;
    private String gender;

    public Person(String name, int age, String gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
        System.out.println("父类Person的带参数的构造方法");
    }
    public Person(){
        System.out.println("父类Person的不带参数的构造方法");
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public void output(){
        System.out.println("姓名:" +name);
        System.out.println("性别:" +gender);
        System.out.println("年龄:" +age);
    }

}

子类Student

package com.wfu.ch04;

public class Student extends Person {
    private double score;
    private String grade;

    public Student(double score, String grade) {
        this.score = score;
        this.grade = grade;
        System.out.println("子类Student的带参数的构造方法");
    }

    public Student(String name, int age, String gender, double score,
            String grade) {
        super(name, age, gender);
        this.score = score;
        this.grade = grade;
        System.out.println("子类Student的带参数的构造方法,显式调用父类的带参数的构造方法");
    }

    public Student(){
        System.out.println("子类Student的不带参数的构造方法");
    }
    public double getScore() {
        return score;
    }
    public void setScore(double score) {
        this.score = score;
    }
    public String getGrade() {
        return grade;
    }
    public void setGrade(String grade) {
        this.grade = grade;
    }
    public void output(){
        super.output();
        System.out.println("成绩:" +score);
        System.out.println("年级:" +grade);
    }
}

子类Teacher

package com.wfu.ch04;

public class Teacher extends Person{
    private double salary;
    private String department;

    public Teacher(double salary,String department) {
        this.salary = salary;
        this.department = department;
        System.out.println("子类Teacher的带参数的构造方法");
    }
    public Teacher(){
        System.out.println("子类Teacher的不带参数的构造方法");
    }
    public double getSalary() {
        return salary;
    }
    public void setSalary(double salary) {
        this.salary = salary;
    }
    public String getDepartment() {
        return department;
    }
    public void setDepartment(String department) {
        this.department = department;
    }
    public void output(){
        System.out.println("工资:" +salary);
        System.out.println("所属院系:" +department);
    }

}

测试类TestClass

package com.wfu.ch04;

public class TestClass {
    public static void main(String[] args) {
//      Person p=new Person();
//      p.output();
//      Teacher t=new Teacher();
//      t.output();
        Student s=new Student("tom",20,"male",89,"2016");
        s.output();

    }

}

继承的特性

  • (1)Java是单继承的,即一个子类只能继承一个父类,被继承的类叫做父类(超类),继承的类叫做子类(派生类)。
  • (2)在继承过程中,子类拥有父类定义的所有属性和方法,但父类可以通过封装思想隐藏某些数据,然后提供子类可以访问的属性和方法。
//在父类Person中
private String name;//进行封装处理
private int age;
private String gender;
  • (3)当生成子类对象时,Java默认首先调用父类不带参数的构造方法,然后执行该构造方法,生成父类的对象,再去调用子类的构造方法,生成子类的对象。要想生成子类的对象,首先生成父类的对象,没有父类对象就没有子类对象。
//例如在测试类中如果只写
Teacher t=new Teacher();
t.output();//运行结果是先把父类中不带参数的类执行,然后再执行 t.output() 方法
  • (4)如果一个类没有指明任何父类,则缺省的自动继承java.lang.Object类。Object类是所有类的*父类,在java中,所有类都是直接或间接的继承了Object类。
  • super关键字:super关键字代表父类对象,主要有两个用途:
    1)调用父类的构造方法
    super表示对父类对象的引用。如果子类使用super()显示调用父类的某个构造方法,那么在执行的时候就会寻找与super()所对应的构造方法而不再去寻找父类的不带参数的构造方法。super必须作为构造方法的第一条语句,前面不能有其他的可执行语句。
    2)访问父类的属性和方法
    当子类的属性或方法与父类的属性或方法重名时,可用super.属性名或super.方法名(参数列表)的方式访问父类的属性或方法。
//在测试类中
Student s=new Student("tom",20,"male",89,"2016");
s.output();
//这段代码智能输出“成绩”和“年级”,因为会先调用父类的默认的不带参数的方法,而这时父类的不带参数的构造方法是什么都没有的,我们原本的意思是吧“姓名”、“年龄”、“性别”、这三个也输出。这时就要用到super
应该写成:
super.output();
Student s=new Student("tom",20,"male",89,"2016");
s.output();

多态

多态:多态是指在父类中定义的属性或方法被子类继承之后,可以具有不同的表现行为。这使得同一个属性或方法在父类及其各个子类中具有不同的语义。如:动物会“叫”,“猫”和“鸟”都是动物的子类,但其“叫”声是不同的

重写

当子类继承父类时,可以在子类中直接使用父类的属性和方法。如果父类的方法无法满足子类的需求,则可以在子类中对父类的方法进行改造,这称为方法的重写,重写是java多态性的一种体现。

  • (1)、方法重写:又叫做覆写,子类与父类的方法返回值类型一样,方法名称一样,参数一样,这样我们说子类与父类的方法构成了重写关系。若给子类的run方法添加一个参数,则不叫重写。分别调用带参数的run和不带参数的run来执行一下。
public class Test2 {
    public static void main(String[] args) {
        Dog dog=new Dog();
        dog.run();
    }
}
class Animal{
    public void run(){
        System.out.println("Animal is running!");
    }
}
class Dog extends Animal{
    public void run(){
        System.out.println("Dog is running!");
    }
}
  • (2)、方法重写与方法重载之间的关系:重载发生在同一个类内部的两个或多个方法。重写发生在父类与子类之间。
  • (3)、方法重写需要遵循以下几点:
    重写的方法的签名必须要和被重写的方法的签名完全匹配;
    重写的方法的返回值必须和被重写的方法的返回一致或者是其子类;
    重写的方法所抛出的异常必须和被重写方法的所抛出的异常一致,或者是其子类;
    私有方法不能被重写子类重写父类方法的过程中,可访问性只能一样或变的更公开。
  • 我们说子类就是父类(玫瑰是花,男人是人),因此多态的意思是:父类型的引用可以指向子类的对象。
    (1)多态:父类型的引用可以指向子类型的对象。
public class Test3 {
    public static void main(String[] args) {
        Flower flower=new Rose();//多态
        flower.sing();
    }
}
class Flower{
    public void sing(){
        System.out.println("Flower is sing.");
    }
}
class Rose extends Flower{

}

花是花,玫瑰是玫瑰,玫瑰是花,但花是玫瑰是错误的,花是玫瑰,那么康乃馨呢是花吗?对不对呀。
(2)、Flower flower=new Rose();当使用多态方式调用方法时,首先检查父类中是否有Sing方法,如果有,则去调用子类的sing方法(不管是继承的还是重写的)。如果没有则编译错误。因为flower是一个Flower类型的变量,如果Flower类型没有这个sing方法,则无法调用。

上一篇:C++的三大特性:封装、继承和多态性的详解


下一篇:局域网内python socket实现windows与linux间简单的消息传送