java第四节 类的继承/抽象/接口/多态性

/*
类的继承
类的继承可以简化类的定义
java只支持单继承,不允许多重继承
可以有多层继承,即一个类可以继承其一个类的子类,如类B继承了类A,类C又可以继承类B
那么类C也间接继承了类A

子类继承父类所有的成员变量和成员方法,但不继承父类的构造方法,
在子类的构造方法中可使用语句super(参数列表)
调用父类的构造方法

如果子类的构造方法中没有显式地调用父类构造方法,也没用使用this关键字调用重载的其它构造方法,则在产生子类的实例对象时
系统默认调用父类无参数的构造方法

子类对象的实例化过程

1 分配成员变量的存储空间并进行默认的初始化,就是用new关键字产生对象后
  对类中的成员变量按第三章的表3.1的对应关系对对象中的成员变量进行初始化赋值

2 绑定构造方法参数,就是new Person(实际参数列表)中所传递进的参数赋值给构造方中的形式参数变量

3 如果有this()调用,则调用相应的重载构造方法(被调用的重载构造方法又从步骤2开始执行这些流程)
  被调用的重载构造方法的执行流程结束后,回到当前构造方法,当前构造方法直接跳转到步聚6执行

4 显示或隐式追溯调用父类的构造方法(一直到Ojbect类为止,Object是所有java类的最顶层父类)
  在本音后面部分有详细讲解,父类的构造方法又从步骤2开始对父类执行这些流程,父类的构造方法的执行流程结束后,回到当前构造方法,当前构造方法继承往下执行

5 进行实例变量的显示初始化扣喺,也就是执行在定义成员变量时就对其进行赋值的语句

6 执行当前构造方法的方式体中的程序代码

1):为什么super()和this()调用语句不能同时在一个构造函数中出现?
   因为当在一个构造函函数中出现this()调用以后,那么去别外一个构造函数将也会直接默认或指定的super()方法
   如要执行完成以后,返回到初始的构造函数还让执行super()方法时,那就又是重复操作了,无意义
   所以编译也不会通过的


2):为什么super()和this()调用语句只能作为构造函数的第一句出现
   如果不是作为第一句出现,编译也会出错的
   如果选执行一些赋值语句,然后执行this或super()函数
   那么就跟我们的执行流程相矛盾了
   因为构造函数需要需要执执行this,如果没有this执行super()方法
   编译器也不会让通过的


覆盖父类的方法
   覆盖方法必须和被覆盖方法具有相同的方法名称,参数列表和返回值类型

   如果在子类中想调用父类中那个被覆盖的方法,我们可以用super方法的格式

   覆盖方法时,不能使用此父类中被覆盖的方法更严格的访问权限

   
final关键字
   1 在java中声明类,属性和方法时,可以使用关键字final来修饰
   2 final标记的类不能被继承
   3 final标记的方法不能被子类重写
   4 final标记的变量(成员变量或局部变量)即成为常量,只能赋值一次
   5 方法中定义的内置类只能访问该方法内的final类型的局部变量
     用final定义的局部变量相当于是一个常量,它的生命周期超出了方法运行的重命周期
	 将一个行参定义成final也是可以的,这就是限定了我们在方法中修改形式参数的值
   6 public static final共同标记常量时,这个常量就成了全局常量

抽象类
   java中可以定义一些不含方法体的方法,它的方法体的实现交给该类的子类根据自己的情况去实现
   这样的方法就是抽象方法,包含抽象方法的类叫做抽象类

   1 抽象类必须使用abstract关键字来修饰,抽象方法也必须用abstract来修饰
   2 抽象类不能被实例化,也就是不能用new关键字去产生对象
   3 抽象类只需声明,而不需实现
   4 含有抽象方法的类必须声明为抽象类,抽象类的子类必须覆盖所有抽象方法后才能被实例化,否则这个子类还是个抽象类

*/

//final class Person 将不能被继承了
class Person
{
	//protected final String name = "unknown"; 变量为final时将不能被子类赋值了
	protected String name = "unknown";


	//public final String x = "abc"; //第一种赋值是初始赋值

	public  final String x;
    //public static final String x;

	public static final String y = "abc";




	public int age = -1;

	public Person()
	{
	    this.x = "cde";
	}

    public Person(String name, int age)
	{
	    this.name = name;
		this.age = age;
		//或者在构造函数中进行赋值
		this.x = "abc";

	}

    //public void getInfo(){} 将不能在子类重写了
	public void getInfo()
	{
		//this.x = "abc"; //用final定义的变量将不能被修改了
	    System.out.println("name:"+name+", age:"+age);
	}
};


class Student extends Person
{

	public String school = "unknown";

	public Student()
	{
	    //super("xlc",15);
		super();
	}

	public Student(String name, int age, String school)
	{
	   
	    this(name,age); //调用自己的构造函数
		this.school = school;
		//this(name,age); //调用自己的构造函数
	}

	public Student(String name, int age)
	{
	     super(name, age);
	}

	public void getInfo()
	{
	     System.out.println("school:"+school+"name:"+name+", age:"+age);
		 super.getInfo();
	}

	public void study()
	{
	
	}
};

class TestStudent
{
	public static void main(String[] args)
	{
	    
		//Student st = new Student();
		//st.name = "xlc";
		//st.age = 34;
		//st.getInfo();

		Student st = new Student("xlc",22,"清华大学");
		st.getInfo();

		System.out.println(Float.MAX_VALUE);
	}
};

  

/*
接口(interface)
如果一个抽象类中的所有方法都是抽象的,我们就可以将这个类用另外一种方式来定义,也就是接口定义
接口是抽象方法和常量值的定义的集合,从本质上讲,接口是一种特殊的抽象类
这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现

1 接口中的成员都是public访问类型的,接口的变量默认是用public static final标识的

2 我们可以定义一个新的接口用extends 关键字去继承一个已有的接口

3 我们也可以定义一个类用implements关键字去实现一个接口中的所有方法,我们还可以去定义一个抽旬类用implements关键字去实现一个接口中定义的部分方法

4 一个类可以继承一个父类的同时,实现一个或多个接口,extneds关键字必须位于implements关键字之前


对象的类型转换
   1 子类对象可以自动转换成父类
   2 父类转换为子类必须使用强制转换
   3 instanceof操作符可以用它来判断一个实例对象是否属于一个类
   4 Object类及equals方法


*/
/*abstract class A
{
	abstract int aa(int x, int y);

    //抽象类将不能实例化


};


class B extends A
{
     int aa(int x, int y)
	 {
	 
	     return 1;
	 }
};*/


interface Runner
{
    int ID = 1;

	void run();
}

interface Animal extends Runner
{
     void breathe();
}


class Fish implements Animal
{
     public void run()
	 {
	     System.out.println("fish is swimming");
	 }

	 //public void breathe()
	 public void breathe()
	 {
	     System.out.println("fish is bubbling");
	 }

	 public static void main(String[] args)
	 {
	      Fish f = new Fish();
		  int j=0;
		  j = Runner.ID;
		  j = f.ID;
		  //f.ID = 2; //常量不能被赋值

	 }
};

abstract class LandAnimal implements Animal
{
	public void breathe()
	{
	
	}
};



interface dog
{
     void uaau();
}

interface Flyer
{
     void fly();
}

class Bird implements Runner, Flyer
{
	public void run()
	{
	
	}

	public void fly()
	{
	
	}
};




//继承一个类时,可以实现其它接口
//也是可以继承从外接口类的
class Student extends Person implements Runner, dog
//如果继承类和接口,extends必须在implements之前
{
	
	public void run()
	{
	
	}

	public void uaau()
	{
	
	}
};


interface A 
{
	//public static final int ID=1;
	//int ID = 1; //这个是一个常量而不是一个变量,接口只能定义常量,不能定义变量,
	//只能定义常量和抽象类

	public static final int ID=1;

    int aa(int x, int y);

	void bb();
}






/*class  
{
	public static void main(String[] args) 
	{
		System.out.println("Hello World!");
	}
}*/

  

/*
面向对象的多态性
1):应用程序不必为每一个派生类(子类)编写功能调用
只需要对抽象基类进行处理即可,这一招叫"以不变应万变",可以大大提高程序的可复用性

2):派生类的功能可以被基类的引用变量引用,这叫向后兼容,可提高程序的可扩充性和可维护性
   以前写的程序可以被后来程序调用不足以为奇,现在写的程序(如callA方法)能调用以后写的程序(以后编写的一个类A的子类,如类D)就了不起了


*/
class A
{
	public void func1()
	{
	    System.out.println("A func1 is calling");
	}

	public void func2()
	{
	    func1();
	}
};

class B extends A
{
	public void func1()
	{
	    System.out.println("B func1 is calling");
	}

	public void func3()
	{
	    System.out.println("B func3 is calling");
	}
};

class C
{
	public static void main(String[] args)
	{
	    
		B b = new B();
		callA(b);

		//A aa = b;
		//callA(new A());
	}

	public static void callA(A a)
	{
		/*if(a instanceof B)
		{
		  B b = (B)a; //强制类型转换
		  b.func1();
		  b.func2();
		  b.func3();
		}else{
		  a.func1();
		  a.func2();
		}*/


		a.func1();
		a.func2();

		//a.func1();
		//a.func2();
		//a.func3();
	}
};


class Student extends Object
{

	 private String name;

	 private int age;

	 public Student(String name, int age)
	 {
	     this.name = name;
		 this.age = age;
	 }


     /*public boolean equals(Object obj)
	 {
	      Student st = null;
		  if(obj instanceof Student)
		  {
		       st = (Student)obj;
			   if(st.name == name && st.age == age)
			   {
			      return true;
			   } else{
			      return false;
			   }
		  }else{
		       return false;
		  }
	 }*/
	 //如果没有覆盖父类的equals方法,那么将返回不等
	 //只是重载了一下函数

	 public static void main(String[] args)
	 {
	     Student st1 = new Student("张三",20);
		 Student st2 = new Student("张三",20);
		 if(st1.equals(st2))
		 {
		     System.out.println("相等");
		 }else{
		     System.out.println("不相等");
		 }
	 }

};



/*class  
{
	public static void main(String[] args) 
	{
		System.out.println("Hello World!");
	}
}*/

  

interface PCI
{
   void start();

   void stop();

}

class NetWrokCard implements PCI
{
    public void start()
	{
	    System.out.println("Send...");
	}

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


class SoundCard implements PCI
{
	public void start()
	{
	    System.out.println("du...");
	}

	public void stop()
	{
	    System.out.println("sound stop...");  
	}
};

class MainBoard
{
	public void usePCICard(PCI p)
	{
		p.start();
		p.stop();
	}
};

class Assembler
{

	public static void main(String[] args)
	{
	     MainBoard mb = new MainBoard();

		 NetWrokCard nc =  new NetWrokCard();

		 SoundCard sc = new SoundCard();

		 mb.usePCICard(nc);
		 mb.usePCICard(sc);

		 //匿名类
		 /*mb.usePCICard(
		   new PCI()
		   {
		        public void start()
				{
				   System.out.println("test start...");
				} 

				public void stop()
				{
				   System.out.println("test end...");
				}
		   }			 
		 );*/

		 //类拟于
		 class A implements PCI
		 {		       
			    public void start()
				{
				   System.out.println("test start...");
				} 

				public void stop()
				{
				   System.out.println("test end...");
				}

		 };
		 mb.usePCICard(new A());

	}
};

  

原文地址:https://www.cnblogs.com/xiangxiaodong/p/3190184.html