• 继承


    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();
    	}
    }
    

      

  • 相关阅读:
    Leetcode 92. Reverse Linked List II
    Leetcode 206. Reverse Linked List
    Leetcode 763. Partition Labels
    Leetcode 746. Min Cost Climbing Stairs
    Leetcode 759. Employee Free Time
    Leetcode 763. Partition Labels
    搭建数据仓库第09篇:物理建模
    Python进阶篇:Socket多线程
    Python进阶篇:文件系统的操作
    搭建数据仓库第08篇:逻辑建模–5–维度建模核心之一致性维度2
  • 原文地址:https://www.cnblogs.com/liuwei6/p/6571846.html
Copyright © 2020-2023  润新知