继承

1、成员的继承

/*
	成员的继承
	子类继承了父类,子类就会继承父类的成员。

	1当子类与父类在同一个包中时,子类继承父类
	public,protected与默认访问全限定的成员。
	2当子类与父类不在同一个包中时,子类继承父类
	public,protected访问权限的成员。

	换一种说法:
	子类继承父类public,protected访问权限的成员。不能
	继承父类private访问权限的成员。如果子类与父类在同一
	个包中,则继承父类默认访问权限的成员。
*/
package in;

public class InheritMember {
	public static void main(String[] args) {
		
	}
}

class Super {
	public int pubX;
	protected int proX;
	int defX;
	private int priX;

	public void pubM() {

	}

	protected void proM() {

	}

	void defM() {

	}

	private void priM() {

	}
}

class Sub extends Super {
	public void f() {
		pubX = 1;
		proX = 1;
		defX = 1;
		//priX = 1;

		pubM();
		proM();
		defM();
		//priM();
	}
}

  2、继承的关键字

         

/*
	继承
	继承使用extends关键字。
	如果A extends B,则A继承B,A就是B的子类,B
	就是A的父类。
	子类继承了父类,子类便是一种特殊的父类,子类
	就会具有父类的能力。
	子类会继承父类的成员,就好像是子类中自己声明的一样。

	继承的优势:
	1 子类继承了父类,子类便具有父类的功能(父类的功能无需
	在子类中重复实现)。这就能够编码代码的重复,实现代码的
	重用。
	2 使用继承有利于程序的维护。以后程序更新时,只需要更新
	父类即可。

	如果没有显式使用extends继承一个类,则该类继承Object类。
	Object是Java中类的祖先。所有类都是Object的直接或间接
	子类。

	类的单继承性
	在Java中,类只支持单重继承。即一个子类只能继承一个
	父类。
*/

public class Inherit {
//public class Inheirt extends Object {
	public static void main(String[] args) {
		Animal a = new Animal();
		a.introduce();
		Tiger t = new Tiger();
		t.introduce();
		Lion l = new Lion();
		l.introduce();
	}
}

class Animal {
	public void introduce() {
		System.out.println("动物的自我介绍");
		System.out.println("突然改变了实现");
	}
}

class Tiger extends Animal {
	/*public void introduce() {
		System.out.println("动物的自我介绍");
	}*/
}

class Lion extends Animal {
	/*public void introduce() {
		System.out.println("动物的自我介绍");
	}*/
}

  3、构造器的继承

          

/*
	构造器的“继承”
	构造器不是方法,也不是类的成员。构造器
	不能被子类所继承。(public的构造器也不能)。
	虽然子类不会继承父类的构造器,但是在子类的构造器
	中,会首先调用父类的构造器。这是一个递归的过程,
	一直调用到Object类的构造器为止。

	如果子类构造器中没有显式的调用父类的构造器,则会调用
	父类无参的构造器。(编译器会自动生成一条语句:super())
	此时,如果父类没有无参的构造器,将会 产生编译错误。

	子类中通过super调用父类的构造器。
	使用super调用父类构造器的规则:
	1 需要使用super调用父类构造器,而不能使用父类构造器
	的名字。
	2 只能在子类的构造器中调用父类的构造器,而不能在
	子类构造器之外调用父类的构造器。
	3 使用super调用父类构造器,必须是子类构造器中的第一条
	语句。

	编译器自动补充super调用父类构造器的情况:
	子类构造器中没有显式的调用父类构造器,又没有使用this
	调用子类其他构造器时,编译器才会补充super()语句,调用
	父类无参的构造器。如果子类构造器中使用this调用了其他
	构造器,则编译器不会补充super()语句,以免进行重复的
	初始化。
*/

public class ConInherit {
	public static void main(String[] args) {
		Sub2 s = new Sub2();
	}
}

class Super2 {
	public Super2(int x) {

	}
	/*public Super2() {

	}*/
}

class Sub2 extends Super2 {
	/*
		Sub2() {
			super();
		}
	*/
	public Sub2() {
		//super(5);
		this(5);
	}

	public Sub2(int x) {
		//super(5);
	}
}

  4、super关键字的使用

/*
	super关键字的使用:
	1 通过super可以调用父类的构造器
	2 通过super可以访问父类的成员。
*/

public class SuperUse {
	public static void main(String[] args) {
		
	}
}

class Super3 {
	public void f() {

	}
}

class Sub3 extends Super3 {
	public Sub3() {
		//调用父类无参的构造器
		super();
	}

	public void f() {
		//通过super访问父类的成员。
		super.f();
	}
}

  5、

public class Teacher {
	private String name;
	private String group;

	public Teacher(String name, String group) {
		this.name = name;
		this.group = group;
	}

	public void introduce() {
		System.out.println("姓名:" + name + ",所在小组:" + group);
	}

	public void teach() {
		System.out.println("知识点讲解");
		System.out.println("总结提问");
	}
}
--------------------------------------
public class JavaTeacher2 extends Teacher {
	public JavaTeacher2(String name, String group) {
		super(name, group);
	}

	public void teach() {
		System.out.println("打开记事本");
		System.out.println("输入代码");
		super.teach();
	}
}
-------------------------------------------------
public class JapanTeacher2 extends Teacher {
	public JapanTeacher2(String name, String group) {
		super(name, group);
	}

	public void teach() {
		System.out.println("打开日语书");
		System.out.println("读单词");
		super.teach();
	}
}

  6、方法的重写

/*
	方法重写
	父类中的方法,在子类中重新又声明一次,就是方法重写。

	重写的规则:
	1 子类方法与父类方法具有相同的名字。
	2 子类方法参数列表需要与父类相同或者与父类擦除后相同。
	3 子类方法的返回类型是父类方法返回类型的可替换类型。
	可替换类型:
	如果是基本数据类型(包含void),则要求子类方法的返回类型
	与父类方法的返回类型一致。
	如果是引用类型,则要求子类方法的返回类型与父类方法一致,
	或者是父类方法返回类型的子类型。
	4 子类方法的访问权限不能低于父类方法的
	访问权限(可以相同)。
	5 子类方法不能比父类方法抛出更多的受检异常。

	我们可以使用@Override注解给编译器提供重写的信息。
	如果@Override标记的方法没有重写父类的方法,将会
	产生编译错误。
*/

public class OverrideTest {
	public static void main(String[] args) {
		
	}
}

class Super4 {
	public void f1() {

	}

	public void f2() {

	}

	/*public int f3() {

	}*/
	public Object f3() {
		return new Object();
	}

	/*public void f4() {

	}*/
	public void f4() {

	}
}

class Sub4 extends Super4 {
	public void g() {

	}
	//不是重写,而是重载。
	//@Override
	public void f2(int x) {

	}

	/*public byte f3() {

	}

	public Object f3() {

	}*/

	public String f3() {
		return "";
	}

	/*protected void f4() {

	}*/
}

  7、成员变量的隐藏

/*
	成员变量的隐藏
	在子类中声明了与父类同名的变量,则称
	子类隐藏了父类同名的成员变量。
*/
public class Hidden {
	public static void main(String[] args) {
		
	}
}

class Super5 {
	int a;
}

class Sub5 extends Super5 {
	//变量的隐藏。
	int a;
}

  8、父类引用与子类引用(对象)

        

/*
	父类引用与子类引用(对象)
	父类的引用既可以指向父类的对象,也可以指向子类
	的对象(因为子类是一种特殊的父类,所有的子类都
	是父类),子类的引用可以指向子类的对象,但是不能
	指向父类的对象。
	子类可以赋值给父类,但父类不能赋值给子类。

	引用类型之间的转换:
	1 自动转换 子类型向父类型的转换(向上转型)
	2 强制转换 父类型向子类型的转换(向下转型)
	当进行强制转换时,父类引用指向必须是子类对象时,
	才能够真正的转换成子类的类型,否则,编译时没有
	问题,但在运行时会产生ClassCastException异常。

	引用类型转换只能发生在具有父子关系的两个类型
	之间,而不能发生在无父子关系的类型之间(编译
	错误)。

	通过父类的引用不能访问子类新增的成员。即使
	父类的引用指向的确实是一个子类的对象也不行。
*/

public class Reference {
	public static void main(String[] args) {
		Super6 sup = new Super6();
		Sub6 sub = new Sub6();

		//自动转换
		//sup = sub;
		//sup = new Sub6();
		//错误
		//sub = sup;
		//sub = new Super6();
		sup = new Sub6();
		//错误,不能访问子类新增的成员。
		//sup.newM();
		sub = (Sub6)sup;
		sub.newM();
		//错误,没有父子关系。
		//String s = (String) sup;
	}
}

class Super6 {
	
}

class Sub6 extends Super6 {
	public void newM() {
		System.out.println("子类新增加的成员");
	}
}

  9、

/*
	instanceof
	判断左侧操作数是否为右侧操作数的类型(或者右侧操作数的
	子类型),如果是,返回true,否则返回false。

	instanceof 要求两侧操作数的类型具有父子关系,否则
	会产生编译错误。

	instanceof的应用
	如果instanceof返回true,则我们就可以放心的将左侧
	操作数转换成右侧操作数的类型,而不会在运行时产生
	ClassCastException异常。
*/
public class InstanceOf {
	public static void main(String[] args) {
		String s = "abc";
		System.out.println(s instanceof String);
		System.out.println(s instanceof Object);
		//System.out.println(s instanceof InstanceOf);
		InstanceOf i = new InstanceOf();
		System.out.println(i instanceof InstanceOf);
		Object o = new Object();
		System.out.println(o instanceof String);

		i.dodoSomething(new Sub6());
		i.dodoSomething(new Super6());
	}

	public void doSomething(Super6 sup) {
		//Sub6 sub = (Sub6) sup;
		//sub.newM();
		//进行判断,然后在转换,这样就可以避免
		//在运行时产生ClassCastException异常。
		if (sup instanceof Sub6) {
			Sub6 sub = (Sub6) sup;
			sub.newM();
		}
	}
}

  10、多态          

/*
	多态
	多种形态,运行时会根据对象的真正类型,
	来决定调用哪一个类型的方法。
*/
public class Py {
	public static void main(String[] args) {
		Py p = new Py();
		p.doSomething(new Super7());
		p.doSomething(new Sub71());
		p.doSomething(new Sub72());
		p.doSomething(new Sub73());
	}

	public void doSomething(Super7 sup) {
		sup.f();
	}
}

class Super7 {
	public void f() {
		System.out.println("Super7");
	}
}

class Sub71 extends Super7 {
	@Override
	public void f() {
		System.out.println("Sub71");
	}
}

class Sub72 extends Super7 {
	@Override
	public void f() {
		System.out.println("Sub72");
	}
}

class Sub73 extends Super7 {
	@Override
	public void f() {
		System.out.println("Sub73");
	}
}

  11、重写与隐藏       

/*
	重写与隐藏
	实例方法可以被子类重写,静态方法,静态成员变量
	与实例成员变量只能被子类隐藏,不能被子类重写。
	重写可以实现多态,是根据运行时引用指向的对象真正
	类型,来决定调用哪一个类的成员(实例方法)。
	隐藏不能实现多态,是根据编译时引用的类型来决定
	访问哪一个成员。
	能否实现多态,是重写与隐藏的本质区别。
*/

public class OverrideAndHidden {
	public static void main(String[] args) {
		Sup8 sup = new Sub8();
		sup.m();
		sup.staM();
		System.out.println(sup.x);
		System.out.println(sup.staX);
	}
}

class Sup8 {
	int x = 1;
	static int staX = 2;

	public void m() {
		System.out.println("sup m");
	}

	public static void staM() {
		System.out.println("sup staM");
	}


}

class Sub8 extends Sup8 {
	int x = 111;
	static int staX = 222;

	public void m() {
		System.out.println("sub m");
	}

	public static void staM() {
		System.out.println("sub staM");
	}
}

  12、

public class Evaluate {
	public static void main(String[] args) {
		Evaluate e = new Evaluate();
		e.evl(new JavaTeacher2("t1", "g1"));
		e.evl(new JapanTeacher2("t2", "g2"));
		//e.evl(new EnglishTeacher2("t3", "g3"));
	}
	
	/*
	public void evl(JavaTeacher2 t) {
		t.introduce();
		t.teach();
	}

	public void evl(JapanTeacher2 t) {
		t.introduce();
		t.teach();
	}
	*/

	/*
	程序耦合性太高,明天如果增加新的老师,
	则该程序还需要进行修改。
	public void evl(EnglishTeacher t) {
		t.introduce();
		t.teach();
	}
	*/

	/*
		程序修改:
		使用一个父类来表示。
		参数使用父类的类型,这样只需要一个方法。
		父类类型既可以接受父类的对象,也可以接受
		所有子类的对象。
	*/
	public void evl(Teacher t) {
		t.introduce();
		t.teach();
	}
}

  

posted @ 2017-03-18 10:22  凌-风  阅读(258)  评论(0编辑  收藏  举报