一、子类与父类

Java不支持多重继承,即子类只能有一个父类

1.子类

通过使用关键字 extends 来定义一个类的子类。例如:

class Student extends People{.......}

一个类有且仅有一个父类,但一个类可以有多个或零个子类。

二、子类的继承性

1.子类和父类在同一个包中,子类可以继承不是private的成员变量和不是private的方法,继承的成员变量和方法的访问权限保持不变。子类不继承父类的私有成员变量。

2.子类和父类不在同一个包中时,子类只能继承父类的protected和public访问权限的成员变量和方法,不能继承友好访问权限的和private的成员变量和方法。

but,子类可以通过其父类中的一部分方法操作这部分未继承的变量。例如

class People{
	private int hight = 150;
	int gethight(){
		return hight;
	}
}
class Student extends People{
	int add;
	public void setadd(int h){
//		add = h + hight;  非法的,子类不能继承hight
		add = h;
	}
	public int getadd(){
		return add;
	}
}

public class zileiPrivate {

	public static void main(String[] args) {
		Student stu = new Student();
		System.out.println("子类对象未继承的hight:" + stu.gethight());
		stu.setadd(30);
		System.out.println(stu.getadd());
	}

}

3.对protected的理解:①在A类中用A本身创建了一个对象,则这个对象可以继承次类本身和其父类的protected成员变量和方法。②在object类中用A类创建了一个对象O,那么,若A类和object类在同一个包中,对象O就可以访问A类中protected成员变量和方法。若A类的父类和object类在同一个包中,对象O就可以访问继承A类父亲的protect对象和方法。

4.instanceof运算符:iinstanceof是Java独有的双目运算符,左边操作元是对象,右边操作员是类,若左边的对象是右边的类的类或者子类是则返回true,否则,返回false。例如在上面代码中加入:System.out.println(stu instanceof People);  其运行结果为true。

三、成员变量的隐藏和方法重写

1.成员变量的隐藏

子类声明的成员变量名字和父类的成员变量名字相同时(其类型可以不同),子类会隐藏从父类继承的成员变量。

子类隐藏父类的成员变量的特点:

①:子类对象 或者 子类自己定义的方法 操作 与 父类同名的成员变量时 ,操作的是子类中声明的成名变量。

②:子类 继承父类中的方法 所操作的成员变量 是被隐藏的父类的成员变量。也就是说子类调用父类中的方法时里面的同名变量是父类的,而不是子类重新声明的。

例如:  其结果为121.8   120

class price{
	public double weight;
	
	public double getOldPrice(double w){
		weight = w;
		return weight*10;
	}
}

class cheapPrice extends price{
	public int weight;
	public int getNewPrice(int w){
		weight = w;
		return weight*10;
	}
}

public class Goods {
	public static void main(String[] args) {
		cheapPrice p = new cheapPrice();
		System.out.println(p.getOldPrice(12.18));
		System.out.println(p.getNewPrice(12));
	}

}

2.方法重写

方法重写又称方法覆盖,子类通过重写方法可以隐藏已继承的方法。其规则为:重写方法的名字、参数个数、参数的类型 和父类的方法完全相同。(在不同的类 且不是子类继承关系的类 中,若方法的名字、参数个数、参数的类型相同则是没有影响的 ,不叫方法的重写。)

重写方法可以操作父类的成员变量和方法,也可以操作子类的成员变量和方法,但无法操作被子类隐藏了的成员变量和方法。

如果子类想要使用被隐藏的方法或成员变量,必须使用关键字super。

3.super关键字

①:用super操作被隐藏的成员变量和方法。如super . wight 、super.getOldPrice()。

②:使用super调用父类中的构造函数。(子类不能继承父类的构造方法,当在 子类的构造方法 中使用super来调用 父类的构造方法 时,super必须是子类构造方法中的头一条语句。)

super中的参数名字与子类构造函数参数名相同,但其参数类型、个数、顺序与父类中的构造函数相同

class People{
	int age;
	String name;
	People(){
	}
	People(int n,String name){
		age = n;
		name = name;
		System.out.println("My name is " + name);
		System.out.println("I am " + age + " years old");
	}
}

class Student extends People{
	boolean 恋爱否;
	Student(int nianji,String xingming,boolean f){
		super(nianji,xingming);
//super中的参数名字与子类构造函数参数名相同,但其参数类型、个数、顺序与父类中的构造函数相同
		恋爱否 = f;
		System.out.println("恋爱了吗?" + '\n' + "回答:" + f);
	}
}

public class gouzaosuper {
	public static void main(String[] args) {
		Student stu = new Student(18,"hd",false);
		
	}
}

4.多态性 

多态性就是指父类的某个方法被其子类重写时,可以各自产生自己的功能行为。

5.final关键字

final关键字可以修饰类、成员变量和方法中的局部变量。

final类不能被继承,即不能有子类。

被final修饰的父类方法不能被子类重写

被final修饰的成员变量或局部变量必须初始化 且在运行期间不允许在发生变化,也就是成为了一个常量了。

四、对象的上转型对象

什么是上转型对象?举一个例子,“ 动物 ”是一个父类,“ 老虎 ” 是 “ 动物 ” 的子类,现在声明了一个 “ 动物 ”  A ,但是把老虎的对象赋值给了A(即  动物  A;  A = new  老虎();)(或者 动物  A;  老虎  B =  new  老虎(); )这样就称对象A 是子类对象B的上转型对象。

上转型对象的特点:

①:上转型对象不能操作子类新增的成员变量,不能调用子类新增的方法。

②:上转型对象可以访问子类继承或隐藏的成员变量和方法。(但是书上面又说,如果子类重写了父类的某个实例方法后,当对象的上转型对象调用这个实例方法时 是调用的子类重写的实例方法,这点很迷。)

③:可以将对象的上转型对象再强制转换到一个子类对象。

④:不可以将父类创建的对象的引用赋值给子类声明的对象。

⑤:如果子类重写了父类的静态方法,那么子类对象的上转型对象不能调用子类重写的静态方法,只能调用父类的静态方法。

class People{
	void tryLove(String s){
		System.out.println(s);
	}
}

class Student extends People{
	void men(int i,int n){
		int love = i + n;
		System.out.println(love);
	}
	void tryLove(String s){
		System.out.println("***" + s + "***");
	}
}

public class gouzaosuper {
	public static void main(String[] args) {
		People women;
		Student andy = new Student();
		women = andy;
		women.tryLove("Try Love");
		//这里调用的就是子类重写的方法,而不是父类的tryLove()
		//等同于women.tryLove("Try Love");
		
		Student hd = (Student)women;
		//把women(上转型对象)强制转换成子类Student型
		hd.men(500, 20);
	}
}

五、abstract类和abstract方法

abstract 即抽象,抽象类和抽象方法。

对于abstract方法,只允许声明,不允许实现(没有方法体),而且不允许使用final 和 abstract 同时修饰一个方法或类,也不允许使用static 修饰 abstract方法,即 abstract方法必须是实例方法。

①:abstract类里面可以有abstract方法,也可以有不是abstract的方法(不是abstract的类中不可以有abstract方法)。

②:abstract类不能用new运算符创建对象。如果一个非抽象类是某个抽象类的子类,那么他必须重

写父类的所有抽象方法,并给出方法体。

③:abstract类的子类。如果一个abstract类是abstract类的子类,他可以重写父类的abstract方法,也可以继承父类的abstract方法。

④:abstract类的对象作上转型对象。可以使用abstract类声明对象,尽管不能使用new创建该对象,但该对象可以成为其子类对象的上转型对象,那么该对象就可以调用子类重写的方法了。

abstract class GirlFriend{
	abstract void speak();
	abstract void cooking();
}
class ChinaGirlFrend extends GirlFriend{
	void speak(){
		System.out.println("你好");
	}
	void cooking(){
		System.out.println("fish");
	}
}
class AmericanGirlFriend extends GirlFriend{
	void speak(){
		System.out.println("hello");
	}
	void cooking(){
		System.out.println("beef");
	}
}
	
class Boy{
	GirlFriend friend;
	void setGirlfriend(GirlFriend f){
		friend = f;
	}
	void showGirlFriend(){
		friend.speak();
		friend.cooking();
	}
}
public class ChouXiang {
	
	public static void main(String[] args) {
		GirlFriend girl = new ChinaGirlFrend();
		//girl是ChinaGirlFrend()的上转型对象
		Boy boy = new Boy();
		boy.setGirlfriend(girl);
		boy.showGirlFriend();
		girl = new AmericanGirlFriend();
		//girl是AmericanGirlFriend()的上转型对象
		boy.setGirlfriend(girl);
		boy.showGirlFriend();
	}

}

在设计程序时,经常会使用abstract类,其原因是,abstract类只关心操作,而不关心这些操作具体的实现细节,可以使程序的设计者把主要精力放在程序的设计上,而不必拘泥于细节的实现。细节由抽象类的非抽象子类去实现,这些子类可以给出具体的实例,来完成程序功能的具体实现。在设计一个程序时,可以通过在abstract类中声明若干个abstract方法,表明这些方法在整个系统设计中的重要性,方法的内容细节由他的非abstract子类去完成。

使用多态进行程序设计的核心技术之一是使用上转型对象,即  将abstract类声明的对象作为其子类对象的上转型对象,那么这个上转型对象就可以调用子类重写的方法。

所谓面向抽象编程,是指当设计某种重要的类时,不让该类面向具体的类,而是面向抽象类,即所设计类中的重要数据是抽象类声明的对象,而不是具体类声明的对象。

面向抽象编程的目的是为了应对用户需求的变化,将某个类中经常因需求变化而需要改动的代码分离出去。面向抽象编程的核心是让类中每种可能的变化对应的交给抽象类的一个子类去负责,从而让该类的设计者不去关心具体的实现,避免所设计的类依赖与具体的实现。面向抽象编程使设计的类容易应对用户需求的变化。