290 likes | 498 Views
主要内容: * 类的继承 * 继承时候的构造方法 * 隐藏和覆盖 * 重载、覆盖和重载的区别 * Object 类 * 终结类、终结方法 * 抽象类、抽象方法 * 接口. 一、类的继承关系. class TrashCar extends Car { int capacity; void set_capacity(int trash_car_capacity) { capacity=trash_car_capacity; } void show_capacity();
E N D
主要内容: * 类的继承 * 继承时候的构造方法 * 隐藏和覆盖 * 重载、覆盖和重载的区别 * Object类 * 终结类、终结方法 * 抽象类、抽象方法 * 接口
一、类的继承关系 class TrashCar extends Car { int capacity; void set_capacity(int trash_car_capacity) { capacity=trash_car_capacity; } void show_capacity(); { System.out.println(“My capacity is: ”+ capacity); } } class Car { int car_number; void set_number(int car_num) { car_number=car_num; } void show_number() { System.out.println (“My car No. is :”+car_number); } }
class CarDemo { public static void main(String args[ ]) { TrashCar DemoTrashCar=new TrashCar( ); DemoTrashCar.set_number(4949); DemoTrashCar.set_capacity(20); DemoTrashCar.show_number( ); DemoTrashCar.show_capacity( ); } } • TrashCar中继承了Car中的两个方法 Car是父类,TrashCar是子类
何时选择继承性 • 一个很好的经验: “B is A?”,如果是则让B做A的子类 常犯的错误A有一个B吗? 例如让汽车轮子成为汽车的子类是错误的
一、类的继承 子类可以访问父类中的成员变量和成员方法? 1、父类中的公有(public)成员,可以被子类直接访问。 2、父类中的私有(private)成员,不能被子类直接访问,但是父类如果提供了公有的方法来访问其私有成员,则子类可以通过父类的公有方法来访问私有成员。
出错,b不能直接访问 e.g public class B{ public int a=10; private int b=11; protect int c=12; public int getB(){return b;} } public class A extends B{ public void tryVariables() { System.out.println(a+b+c+getB()); } } getB()没有问题,因为它是从父类继承过来的公有方法
二、继承时候的构造方法 构造方法是一种特殊的方法,可以重载,不能从父类继承。 有继承时,构造方法遵循的原则: 1、子类不能继承父类的构造方法; 2、子类可以调用父类的某一个构造方法 super();super(name,adress); 3、子类的构造方法没有明确调用父类的构造方法,则系统在执行子类的构造方法时会自动调用父类的默认构造方法(无参数的构造方法) 4、若子类的构造方法中调用了父类的构造方法,则调用语句必须是子类构造方法的第一句
public class Person{ protect String name,address; public Person(){ this(“”, “”);} public Person(String aName,String anAddress){ name=aName; address=anAddress; } }//父类
Person(); public class Employee extends Person{ protect int employeeNumber; protect String workPhoneNumber; public Employee(){ this(0, “”); } public Employee(int aNumber,String aPhoneNumber){ employeeNumber=aNumber; workPhoneNumber=aPhoneNumber; } } 此处隐含调用构造方法 Person()
调用父类的无参数构造函数 public class Professor extends Employee{ protected String research; public Professor(){ super(); research=“”; } public Professor(int aNumber,String aPhoneNumber,String aResearch){ super(aNumber,aPhoneNumber); research=aResearch; } } 调用父类的参数相对应的构造函数
习题1、有关类Demo,哪句描述是正确的? public class Demo extends Base{ private int count; public Demo(){ System.out.println("A Demo object has been created"); } protected void addOne() {count++; } } A 当创建一个Demo类的实例对象时,count的值为0。 B 当创建一个Demo类的实例对象时,count的值是不确定的。 C 超类对象中可以包含改变count 值的方法。 D Demo的子类对象可以访问count。
练习2、当编译和运行下列程序段时,会发生什么? class Base {} class Sub extends Base {} class Sub2 extends Base {} public class CEx{ public static void main(String argv[]){ Base b = new Base(); Sub s = (Sub) b; } } A 通过编译和并正常运行。 B 编译时出现例外。 C 编译通过,运行时出现例外。
三、隐藏和覆盖 1、属性的隐藏:子类中重新定义了父类的属性,且子类中属性的类型和名字同父类相同,则子类中隐藏了父类的同名属性。 2、方法的隐藏:子类中重新定义了父类的方法,且子类中方法的返回值类型、方法名以及方法的参数的个数、顺序、类型完全与父类相同,则子类中隐藏了父类的同名方法。
覆盖了父类的变量a class SuperHide{ int a=1; int b=2; public void myPrint(){ System.out.println("super"); } } class HideTest extends SuperHide{ int a=3; public void myPrint(){ System.out.print("CHILD");} public void myPrint(String s){ System.out.print(s); } public static void main(String arg[]){ HideTest ht=new HideTest(); System.out.println(ht.a); ht.myPrint(); ht.myPrint("ok"); } } 覆盖了父类的方法myPrint() 重载方法myPrint()
四、覆盖和重载的区别 覆盖:1、方法名必须相同 2、方法参数、返回类型必须完全相同 3、覆盖方法的允许访问范围不能小于原方法 4、覆盖方法所抛出的异常不能比原方法多 重载:1、方法名必须相同 2、方法的参数必须不同 3、重载方法的返回类型可能不同。
A 编译时会出现例外。 B 运行结果为:a is Firstb is secondC 运行结果为:a is Firstb is Secong a.k.a 2ndD 运行结果为:a is First a.k.a 1ndb is Second a.k.a 2nd 练习三、下面的哪个选项是正确的? class ExSuper{ String name; String nick_name; public ExSuper(String s,String t){ name = s;nick_name = t; } public String toString(){ return name; } } public class Example extends ExSuper{ public Example(String s,String t){ super(s,t); } public String toString(){ return name +"a.k.a"+nick_name;} public static void main(String args[]){ExSuper a = new ExSuper("First","1st");ExSuper b = new Example("Second","2nd");System.out.println("a is"+a.toString());System.out.println("b is"+b.toString());}}
五、Object类 Object类是java程序中所有类的直接或间接父类。 所有的类都是从Object类中派生出来的。Object包含所有java类的公共属性和方法。 * public boolean equals(Object obj) * protect void finalize() throws Trowable * public String toString()
equals()方法的重写。 两个同学的《java语言程序设计》课本是否相等(equals()返回true)?你认为这两本书相等的原则是什么? 1、有人认为:书名+作者+出版社相同,equals()返回true; 2、有人认为:书名+作者+出版社+版次相同,equals()返回true; 所以在你的程序中,根据你的需要来重写equals()方法,用你自己的原则来判断返回值。
六、终结类、终结方法 * 终结类:final class Book{……} * 终结方法: class Book{ private String name; final void setName(String aName){ name=aName; } }
练习:指出下列程序的所有错误? final class First {private int a = 1;int b = 2;} class Second extends First {public void method() {System.out.println(a + b);}} A println()参数应为字符串,因此此处不能调用该方法。 B 因为变量a 是private ,所以在其他类中不能访问a。 C Second 不能继承First。 D 关键字final不能修饰类。
七、抽象类和 抽象方法 • 什么是抽象方法? 声明方法的存在而不去实现它的方法被叫做抽象方法。 • 什么叫抽象类? 声明方法的存在而不去实现它的类被叫做抽象类
Abstract(抽象)类不能直接被实例化,因此一般作为其它类的超类,与final类正好相反Abstract(抽象)类不能直接被实例化,因此一般作为其它类的超类,与final类正好相反 • abstract类中的抽象的方法:在该类中定义但不在该类中提供实现,由继承类提供细节 public abstract class SomeAbstractClass { void method1() { System.out.println(“Hi, Java”); } abstract void method2(); } • 定义抽象方法的类必须是抽象类
// 已有两个类Circle和Rectangle,完成相关参数的计算 class Circle { public int r; Circle(int r) { this.r=r } // this指"这个对象的" public int area( ) { return 3*r*r; } // 取近似 } class Rectange { public int width, height; // 这里不需"this" Rectangle (int w, int h) { width=w; height=h; } public int area( ) { return width*height; } }
假设有若干个Circle以及若干个Rectangle,希望计算它们的总面积。直截了当的做法是将它们分别放到两个数组中,用两个循环,加上一个加法,这种做法是不漂亮的假设有若干个Circle以及若干个Rectangle,希望计算它们的总面积。直截了当的做法是将它们分别放到两个数组中,用两个循环,加上一个加法,这种做法是不漂亮的 • 如果还有其它形状triangle、ellipses等,上述方法显得“累赘”,我们希望有一种统一的表示,例如用一个数组shape[ ],接受所有的形状,然后用 for (i=0;i<shape.length;i++) { area_total += shape[i].area(); }
abstract class Shape { abstract float area(); } class Circle extends Shape { public int r; Circle(int r) { this.r=r;} public float area() { return 3.14*r*r; } } class Square extends Shape { public int width,height; Rectangle (int w, int h) { width=w, height=h; } public float area() { return width*height; } }
八、接 口 接口是抽象类的变体。 在接口中,所有方法都是抽象的。 句法是: public interface Transparency { public static final int OPAQUE=1; public static final int BITMASK=2; public static final int TRANSLUCENT=3; public int getTransparency(); }
八、接口 interface Stack { void push(object x); object pop() ; } • 利用接口可实现多重继承(可同时实现多个接口) • 接口的作用和抽象类类似,指定原型,不直接定义方法的内容 • 关键字implement用来实现方法,即在使用时要给出方法的实际内容 • 接口中的方法和变量是public的 class A extends Applet implements Stack { void push(object x) { …; // 具体内容 } object pop( ) { …; //具体内容 } }
下例表示一个简单的接口和实现它的一个类: interface SayHello { void printMessage(); } class SayHelloImpl implements SayHello { void printMessage() { System.out.println("Hello"); } } interface SayHello强制规定,实现它的所有的类必须有一个称做printMessage的方法,该方法带有一个void返回类型且没有输入参数。
复习: * 类的继承 * 继承时候的构造方法 * 隐藏和覆盖 * 重载、覆盖和重载的区别 * Object类 * 终结类、终结方法 * 抽象类、抽象方法 * 接口