zoukankan      html  css  js  c++  java
  • 继承

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

      

  • 相关阅读:
    服务的有状态和无状态
    微服务-服务治理
    微服务-服务注册与发现
    微服务-技术的选型
    微服务的数据一致性
    微服务的服务拆分
    初识微服务
    REST API风格
    算法
    JS 判断PC、android、ios、微信浏览器
  • 原文地址:https://www.cnblogs.com/liuwei6/p/6571846.html
Copyright © 2011-2022 走看看