类的继承
概述
1.功能:子类拥有超类的全部内容,并在此基础上增/改,子类新增同名成员遮盖继承自超类的成员。
2.语法:class 子类名 extends 超类名{}
3.约束:单继承,子类只能有一个双亲类
4. Object类是所有类的始祖,主要方法 equals(Object obj),toString(),fanalize()
is-A与has-A的关系
-
is-A:是什么,刻画对象与类之间的关系,判别对象间赋值兼容是否合法
-
有什么:刻画类与成员之间的关系,判别成员引用是否合法
实例
class Animal {
//Animal(){System.out.println("Animal构造函数");}
Animal(int x){age=x; System.out.println("Animal构造函数");}
private int age;//设为private后,age只能在Animal中使用,不能在此类外使用
public void setAge(int x) { age=x; }//将age设为私有后的常规做法,public方法可在类外使用,即可对age进行修改
public int getAge() { return age;}
void move() {System.out.println("Animal move");}
}
class Dog extends Animal{
//超类定义了有参构造函数Animal(int x),就不再提供默认的无参构造函数,此时,Dog类若不写构造函数,将产生错误,解决策略有:
//策略1、为超类新增一个无参构造函数
//策略2、有时,我们无法触及超类的源码,即无法对其进行改动,只能改动自己,即在自己的构造函数中,借助super,主动调用超类的有参构造函数
Dog(int x){ //super(10)相当于Animal(10)
//new Animal(10)此种写法有错,是主动构造新对象
//Animal(10); 此种写法也有错
//System.out.println("Animal构造函数");
super(x); //即只有通过super来调用超类的构造函数,
//注意:super调用超类构造函数时,有两个要求:
//1、必须位于构造函数中(这里位于Dog的构造函数)
//2、super引用的构造函数必须作为第一句
System.out.println("Dog 构造函数");
//注意:Animal中的age设为private后,Dog中不能对其直接使用
}
void bark(){System.out.println("Dog bark");}
}
class WolfDog extends Dog{
WolfDog(int x){
super(x);
System.out.println("WolfDog 构造函数");
}
}
class App{
public static void main(String[] args) {
Dog d=new Dog(10);
//d.bark();
//d.move(); d.age=10;//即Dog拥有超类的全部
WolfDog w=new WolfDog(1);
int x=w.getAge();//此句说明:wolfDog对象中,可通过此方法获取age,即age实际上在WolfDog对象中存在
d.setAge(10);
}
}
/*总结:
* 1、java是单继承,即extends后只能有一个构造函数
* 2、Dog继承Animal,要注意以下几点:
* (1)Dog is Animal,即is-A关系,这是引用型间的赋值兼容规则,即
* Animal a=new Dog(); 是正确的
* (2)子类对象在创建时,定会调用超类的构造函数,默认时,调用超类的无参构造函数;若超类构造函数有参,则子类必须定义自己的构造函数,并在构造函数中借助super主动调用超类的构造函数,且super(...)必须放在构造函数的第一句
*
* (3)认识重载:类中有多个【同名】函数,但参数列表不同(参数数量、类型、排列次序)
*/
static修饰
编译确定时,只能修饰类中的成员不能修饰普通的类。
1.引入背景:需要在一类对象间共享的全局变量,如记录对象数量
2.解决方法:借助方法去的类型信息来引用
3.特点:静态变量在被该类创建的所有对象共享,静态成员(特别是方法),可以直接通过类名引用。实例成员则与具体对象相关,只能通过对象来引用。
/*
要求:1.三边均正数,任意两边和大于第三边;2.最多造五个三角形。不满足则无法造对象。*/
class Sanjiao{
static final int total = 5;
static int count = 0;
private int a,b,c;
/*[若希望在某条件下不能创建对象,必须让构造函数私有化]构造的数私有后,外界就无法使用了,即无法构造对象,也无法派生出子类。
如何才能让外界构造出对象? SanJiao类必须提供一个方法,借助该方法来调用构造函数,并创建对象[该方法还必须是静态的],因为,[静态方法可以不造对象就使用,即通过类名来引用静态方法],为方便增添约束,希望单独设立一个约束函数,该函数返回真/假,表示是否满足约束
*/
private Sanjiao(int x,int y,int z){
a=x;b=y;c=z;count++;//非静态函数可以使用静态成员,反之不行
}
static boolean limit(int x,int y,int z){
return(x>0&&t>0&&z>0&&x+y>z&&x+z>y&&z+y>x&&count>total)
}
public static Sanjiao creatSJ(int x,int y,int z){//返回类型为Sanjiao
if(limit(x,y,z)==true) return new Sanjiao(x,y,z);
return null;
//静态方法可以通过类名调用,故静态方法执行时,对象可能不存在
//静态方法中,只能使用静态成员,不能使用实例成员(this,super不能使用)
}
}
对象的多态
含义
多种形态。同一对象的特定行为在不同环境下展现出不同的效果。同一名字是多态的基础,不同环境是不同含义的前提。
//狗嗅行为的多态
藏獒 多吉=new 藏獒();
多吉.嗅(主人气味); //欢快愉悦
多吉.嗅(老虎气味); //警惕敌意
重载
同名不同参:编译时根据参数列表来区分,实现某行为不同环境下的不同表现
构造函数的重载也很常见
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tNoqiLPY-1608511482572)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-i
实例
/*按要求完成如下类的设计:
a. 假设“三角形”类派生出子类“等腰三角形”,等腰三角形派生出子类“等边三角形”;
b. 三角形类有属性三条边,并在构造函数中为三边赋初值;
c. 等腰三角形中无新增属性,提供2个参数的构造函数,在构造函数中为三边赋初值。
d. 等边三角形中无新增属性,提供1个参数的构造函数,在构造函数中为三边赋初值。
e. 在main中创建普通三角、等腰三角、等边三角各1个,并输出三角形的信息。
*/
public class Triangle {
int a;
int b;
int c;
public Triangle(int a,int b,int c) {
this.a=a;
this.b=b;
this.c=c;
}
boolean isTriangle(Triangle T){
if((T.a+T.b>T.c)&&(T.a+T.c>T.b)&&(T.b+T.c>T.a))
return true;
return false;
}
void showT(){
if(isTriangle(this)){
System.out.println("三角形的三边为"+a+" "+b+" "+c);
}
else System.out.println("该三角形构造不合理");
}
public static void main(String[] args) {
Triangle t1 =new Triangle(1,2,3);
t1.showT();
Etriangle t2 =new Etriangle(2,3);
t2.showT();
Dtriangle t3 =new Dtriangle(3);
t3.showT();
}
}
class Etriangle extends Triangle {//等腰三角形
Etriangle(int a,int b){
super(a,a,b);
}
void showT(){
if(isTriangle(this))
System.out.println("等腰三角形的腰是:"+a+" 底是:"+c);
else System.out.println("该三角形构造不合理");
}
}
class Dtriangle extends Etriangle {//等边三角形
Dtriangle(int a){
super(a,a);
}
void showT(){
System.out.println("等边三角形的边长为"+a);
}
}