Java【第七篇】面向对象之类设计

Java类的继承

类继承语法规则

< 修饰符> class < 子类名称> [extends < 父类>] 
{
    <属性和方法的声明>
} 

类的继承

子类继承了父类,就继承了父类的方法和属性。
在子类中,可使用父类中定义的方法和属性,也能够建立新的数据和方法。
于是,子类一般比父类的功能更多。
在Java中,继承的关键字用的是“extends”,即子类不是父类的子集,而是对父类的“扩展”。java

继承规则

Java只支持单继承,不容许多重继承
一个子类只能有一个父类
一个父类能够派生出多个子类
子类不能继承父类中私有的(private)的成员变量和方法app

示例

package com.uncleyong;

import java.util.Date;

public class Person {
    public String name;
    public int age;
    public Date birth;

    private String lover = "lucy";

    public String getInfo(){
        return "name: " + name + ", " +
                "age: " + age + ", " +
                "birth: " + birth+ ", " +
                "lover: " + lover;
    }

}

  

package com.uncleyong;


public class Student extends Person{
    public String school;
}

  

package com.uncleyong;

import java.util.Date;

public class TestPerson {
    public static void main(String[] args) {
    	Student student = new Student();
    	student.name = "Jerry";
    	student.birth = new Date();
    	student.age = 1;
    	student.school = "清华";
		System.out.println(student.getInfo());


        Person person = new Person();
		person.age = 1;
		person.birth = new Date();
		person.name = "Tom";

		System.out.println(person.getInfo());
    }
}  

访问控制

能够对Java类中定义的属性和方法进行访问控制----规定不一样的保护等级: public、protected、default、privateide

方法的重写、覆盖

在子类中能够根据须要对从父类中继承来的方法进行改造—覆盖方法(方法的重置、重写),在程序执行时,子类的方法将覆盖父类的方法。测试

覆盖方法必须和被覆盖方法具备相同的方法名称、参数列表和返回值类型。this

覆盖方法不能使用比被覆盖方法更严格的访问权限。spa

示例

package com.uncleyong;

/**
 * 定义一个ManKind类,包括
 * 成员变量 int sex 和 int salary;
 * 方法 void manOrWorman():根据sex的值显示“man”(sex==1)或者“women”(sex==0);
 * 方法 void employeed():根据salary的值显示“no job”(salary==0)或者“ job”(salary!=0)。
 */
public class ManKind {

    int sex;
    int salary;

    public void manOrWoman(){
        if(sex == 0){
            System.out.println("woman");
        }else if(sex == 1){
            System.out.println("man");
        }
    }

    public void employeed(){
        if(salary != 0){
            System.out.println("job");
        }else{
            System.out.println("no job");
        }
    }

}

  

package com.uncleyong;

/**
 * 定义类 Kids1 继承ManKind,并包括
 * 成员变量 int yearsOld;
 * 方法 printAge() 打印 yearsOld 的值。
 *
 * 在Kids1中从新定义employed() 方法,覆盖父类ManKind中定义的employed()方法,
 * 输出“Kids should study and no job.”
 */
public class Kids1 extends ManKind {

    int yearsOld;

    void printAge(){
        System.out.println("yearsOld: " + yearsOld);
    }

    // 方法重写
    public void employeed() {
        System.out.println("Kids should study and no job.");
    }

    //在Kids1类的main方法中实例化Kids1的对象 someKid,用该对象访问其父类的成员变量及方法。
    public static void main(String[] args) {
        Kids1 someKid = new Kids1();
        someKid.sex = 1;
        someKid.salary = 5000;
        someKid.yearsOld = 25;

        someKid.manOrWoman();
        someKid.employeed();
        someKid.printAge();
    }
}

super 关键字

super的功能

在Java类中使用super来引用父类的成分orm

super可用于访问父类中定义的属性
super可用于调用父类中定义的成员方法
super可用于在子类构造方法中调用父类的构造方法
super的追溯不只限于直接父类对象

构造方法不能继承

子类继承父类全部的成员变量和成员方法,但不继承父类的构造方法
在一个Java类中能够经过两种方式得到构造方法:
  使用系统默认的无参数构造方法
  显式定义一个或多个构造方法
一旦显式定义了构造方法,则系统再也不提供默认构造方法blog


调用父类构造方法

在子类的构造方法中可以使用super(参数列表)语句调用父类的构造方法
若是子类的构造方法中没有显示地调用父类构造方法,也没有使用this关键字调用重载的其它构造方法,则系统默认调用父类无参数的构造方法
若是子类构造方法中既未显式调用父类构造方法,而父类中又没有无参的构造方法,则编译出错继承

示例

package com.uncleyong;

public class Circle {

    protected double radius;

    public Circle() {
        this.radius = 1;
        System.out.println("父类构造方法");
    }

    public double getRadius() {
        return radius;
    }

    public void setRadius(double radius) {
        this.radius = radius;
    }

    public double findArea(){
        return 3.14 * radius * radius;
    }

}

  

package com.uncleyong;

public class Cylinder extends Circle{

    private double length;

    public Cylinder() {
        this.length = 1;
    }

    public double getLength() {
        return length;
    }

    public void setLength(double length) {
        this.length = length;
    }

    /**
     * 返回圆柱的体积
     * @return
     */
    public double findVolume(){
        return super.findArea() * length;  // 这里要加super表示调父类的,不加super表示调本类中的findArea方法
    }

    /**
     * 返回圆柱的表面积
     */
    @Override
    public double findArea() {
        return super.findArea() * 2 + 2 * 3.14 * radius * length;
    }

}

 

package com.uncleyong;

public class TestCylinder {

    public static void main(String[] args) {

        Cylinder cylinder = new Cylinder();

		cylinder.setLength(2);

        //返回表面积
        System.out.println(cylinder.findArea());
        //返回体积
        System.out.println(cylinder.findVolume());
    }

}

多态性及其应用

多态性

多态—在Java中,子类的对象能够替代父类的对象使用(父类类型的变量能够指向子类的对象)
一个变量只能有一种肯定的数据类型
一个引用类型变量可能指向(引用)多种不一样类型的对象

Person p = new Student();
Object o = new Person();//Object类型的变量o,指向Person类型的对象
o = new Student(); //Object类型的变量o,指向Student类型的对象

一个引用类型变量若是声明为父类的类型,但实际引用的是子类对象,那么该变量就不能再访问子类中添加的属性和方法

Student m = new Student();
m.school = “pku”; //合法,Student类有school成员变量
Person e = new Student(); 
e.school = “pku”;	//非法,Person类没有school成员变量 

属性是在编译时肯定的,编译时e为Person类型,没有school成员变量,于是编译错误。

虚拟方法调用(Virtual Method Invocation)

正常的方法调用

Person e = new Person();
e.getInfo();
Student e = new Student();
e.getInfo();

虚拟方法调用(多态状况下)

Person e = new Student();
e.getInfo();	//调用Student类中重写的getInfo()方法

编译时类型和运行时类型:编译时e为Person类型,而方法的调用是在运行时肯定的,因此调用的是Student类的getInfo()方法。—— 动态绑定

instanceof 操做符

x instanceof A:检验x是否为类A的对象,返回值为boolean型。
要求x所属的类与类A必须是子类和父类的关系,不然编译错误。
若是x属于类A的子类B,x instanceof A值也为true。

        Boy b = new Boy();
        System.out.println(">>>>>>>>>>>>>>>>");
        // Boy继承了Student
//        System.out.println(b instanceof Student);  // true;若是Boy没有继承Student,报类型不兼容错误
        // Boy2继承了Boy
        System.out.println(b instanceof Boy2); // false,由于b不是Boy2的对象
        System.out.println(b instanceof Boy); // true,由于b是Boy的对象
        // Boy2继承了Boy
        Boy2 b2 = new Boy2();
        System.out.println(b2 instanceof Boy); // true,由于b2是Boy的对象

对象类型转换 (Casting )

基本数据类型的Casting

小的数据类型能够自动转换成大的数据类型
  如long g=20; double d=12.0f
能够把大的数据类型强制转换(casting)成小的数据类型
  如 floate f=(float)12.0 int a=(int)1200L

对Java对象的强制类型转换称为造型

从子类到父类的类型转换能够自动进行
从父类到子类的类型转换必须经过造型(强制类型转换)实现
无继承关系的引用类型间的转换是非法的
在造型前可使用instanceof操做符测试一个对象的类型

示例

package com.uncleyong;

public class Person {
    protected String name="person";
    protected int age=50;
    public String getInfo() {
        return "Name: "+ name + "\n" +"age: "+ age;
    }
}
class Student extends Person {
    protected String school="pku";
    public String getInfo() {
        return  "Name: "+ name + "\nage: "+ age
                + "\nschool: "+ school;
    }

}
class Graduate extends Student{
    public String major="IT";
    public String getInfo()
    {
        return  "Name: "+ name + "\nage: "+ age
                + "\nschool: "+ school+"\nmajor:"+major;
    }
}

 

package com.uncleyong;

public class TestInstance {

	/*
	          在类中定义方法method1(Person e);
		在method1中:
		(1)根据e的类型调用相应类的getInfo()方法。
		(2)根据e的类型执行:
		若是e为Person类的对象,输出:“a person”;
		若是e为Student类的对象,输出
		“a student”
		“a person ”
		若是e为Graduate类的对象,输出:
		“a graduated student”
		“a student”
		“a person”
	 */

    public void method1(Person e){  // 多态的体现,Person类型的形参能够接收实际Person子类对象
        String info = e.getInfo();  // 动态绑定
        System.out.println(info);

        if(e instanceof Graduate){
            System.out.println("a graduated student");
        }
        if(e instanceof Student){
            System.out.println("a student");
        }
        if(e instanceof Person){
            System.out.print("a person");
        }

        System.out.println("\n");

    }

    public static void main(String[] args) {

        TestInstance ti = new TestInstance();

        Person p1 = new Person();
        ti.method1(p1);

        Person p2 = new Student();
        ti.method1(p2);

        Person p3 = new Graduate();
        ti.method1(p3);



    }

}  

Object 类及其主要方法

Object类

Object类是全部Java类的根父类

若是在类的声明中未使用extends关键字指明其父类,则默认父类为Object类
public class Person {
...
}
等价于:
public class Person extends Object {
...
}
例:
method(Object obj){…}  // 能够接收任何类做为其参数
Object o=new Person;
method(o);

==操做符与equals方法

==操做符

==:引用类型比较引用(是否指向同一个对象);
  Person p1=new Person();

  Person p2=new Person();

  if (p1==p2){…}

基本类型比较值:

  int a=5; if(a==6){…}
用"=="进行比较时,符号两边的数据类型必须一致(可自动转换的基本数据类型除外),不然编译出错;

equals()方法

equals()方法是Object类的方法,因为全部类都继承Object类,也就继承了equals()方法。只能比较引用类型,其做用与“==”相同,比较是否指向同一个对象。格式:obj1.equals(obj2)
特例:当用equals()方法进行比较时,对类File、String、Date及封装类(Wrapper Class)来讲,是比较类型及内容而不考虑引用的是不是同一个对象;
缘由:在这些类中覆盖了equals()方法。

toString 方法

toString()方法在Object类中定义,其返回值是String类型,返回类名和它的引用地址。在进行String与其它类型数据的链接操做时,自动调用toString()方法
  Date now=new Date();
  System.out.println(“now=”+now); 至关于 System.out.println(“now=”+now.toString());  // now=Date@122345
能够根据须要在用户自定义类型中重写toString()方法,如String 类重写了toString()方法,返回字符串的值。
s1=“hello”;
System.out.println(s1);  // 至关于System.out.println(s1.toString());
基本类型数据转换为String类型时,调用了对应封装类的 toString()方法,int a=10; System.out.println(“a=”+a);

示例

package com.uncleyong;

public class GeometricObject {
    protected  String  color;
    protected  double  weight;
}

 

package com.uncleyong;

public class Circle1 extends GeometricObject{
    private double radius;

    public double getRadius() {
        return radius;
    }

    public void setRadius(double radius) {
        this.radius = radius;
    }

    public Circle1() {
        this.radius = 1;
        this.weight = 1;
        this.color = "white";
    }

    public Circle1(double radius) {
        this.radius = radius;
        this.weight = 1;
        this.color = "white";
    }

    public Circle1(double radius, double weight, String color) {
        this.radius = radius;
        this.weight = weight;
        this.color = color;
    }

    public double findArea(){
        return Math.PI * this.radius * this.radius;
    }

    @Override
    public boolean equals(Object obj) {
        if(this == obj){
            return true;
        }

        if(obj == null){
            return false;
        }

        if(!(obj instanceof Circle1)){
            return false;
        }

        Circle1 c = (Circle1) obj;

        return c.getRadius() == this.radius;
    }

    @Override
    public String toString() {
        return "" + this.radius;  // 写为return this.radius;不行,由于radius是double
    }
}

  

package com.uncleyong;

public class TestCircle1 {

    /**
     * 写一个测试类,建立两个Circle对象,判断其颜色是否相等;
     * 利用equals方法判断其半径是否相等;
     * 利用toString()方法输出其半径。
     */
    public static void main(String[] args) {

        Circle1 c1 = new Circle1(1, 2, "Black");
        Circle1 c2 = new Circle1(2, 3, "Black");
        Circle1 c3 = new Circle1(2, 2, "Black");
        Circle1 c4 = new Circle1(2, 3, "Red");

        // 比颜色
        System.out.println(c1.color.equals(c2.color));  // true
        // 比半径
        System.out.println(c1.equals(c2));  // false

        // 比颜色
        System.out.println(c3.color.equals(c4.color));  // false
        // 比半径
        System.out.println(c3.equals(c4));  // true

        System.out.println(c1);  // 1.0   打印对象,会自动调对象的toString方法

    }
}

封装类

针对八种基本定义相应的引用类型—封装类

int i = 10;
Integer j = 10;  // Integer是封装类,基本数据类型10赋给j,自动装箱
相关文章
相关标签/搜索