/*
类变量:又叫静态变量,这种变量属于类,通过类名就可以访问类变量。
实例变量:属于类的实例即对象,通过对象可以访问实例变量,但是不能通过类名访问实例变量。
静态方法:方法属于类,通过对象访问实例方法,不能通过类名访问实例方法。

隐藏:B隐藏了A的变量或者方法,那么,B不能访问A被隐藏的变量或方法,但是,将B转换成A后,可以访问A被隐藏的变量或方法。
覆盖:B覆盖了A的变量或者方法,那么,B不能够访问A被覆盖的变量或方法,将B转换成A后,同样不能访问A被覆盖的变量或方法。

Java中方法和变量在继承时的覆盖与隐藏规则如下:
	父类的实例变量和类变量能被子类的同名变量隐藏。
	父类的静态方法被子类的同名静态方法隐藏。
	父类的实例方法被子类的同名实例方法覆盖。
	不能用子类的静态方法隐藏父类中同样标识的实例方法,否则编译器将会报错。
	不能用子类的实例方法覆盖父类中同样标识的静态方法,否则编译器会报错。
	最终方法(带关键字final的方法)不能被覆盖。
	变量只会被隐藏,不会被覆盖,无论她是实例变量还是静态变量。而且,子类的静态变量可以隐藏父类的实例变量,子类的实例变量可以隐藏父类的静态变量。
*/

public class AccessMethod 
{
	public static void main(String[] args) 
	{
		//先测试继承时变量的覆盖于隐藏问题
		System.out.println("在继承关系中,同名变量的覆盖与隐藏的执行内容如下:");
		ChildClass child = new ChildClass();
		System.out.println("\t创建了ChildClass对象,ChildClass的属性信息如下:");
		System.out.println("name:" + child.name + "; age:" + child.age + "; var:" + child.classVar);
		
		//将ChildClass类型转换成parentClass对象
		ParentClass parent = child;
		System.out.println("将创建的ChildClass对象赋值给ParentClass对象,其属性信息如下:");
		System.out.println("name:" + parent.name + "; age:" + parent.age + "; var:" + parent.classVar);
		
		System.out.println("子类可以访问父类被隐藏的实例变量name:" + child.getParentName());
		System.out.println("子类可以访问父类被隐藏的实例变量age:" + child.getParentAge());
		System.out.println("子类可以访问父类被隐藏的静态变量var:" + child.getParentVar());

		System.out.println("\n<<----------------<<------------>>------------------>>\n");
		
		//再测试继承时方法的覆盖与隐藏问题
		System.out.println("在继承关系中,同名方法的覆盖与隐藏的执行内容如下:");
		child.getName();		//实例方法
		child.getClassVar();	//静态方法
		parent.getName();		//实例方法
		parent.getClassVar();	//静态方法
	}
}

class ParentClass
{
	public static String classVar = "父类的字符串类变量";
	public static int age = 50;	//类变量,ParentClass年龄
	public String name = "ParentClass";	//实例变量,ParentClass的名字

	//静态方法,获取ParentClass的类别
	public static String getClassVar()
	{
		//静态方法中操作的只能是类变量,静态变量
		System.out.println("ParentClass的getClassVar()方法被调用!");
		return classVar;
	}

	//静态方法,获取ParentClass的年龄
	public static int getAge()
	{
		//静态方法中操作的只能是类变量,静态变量
		System.out.println("ParentClass的getAge)方法被调用!");
		return age;
	}

	//实例方法,获取ParentClass的名字
	public String getName()
	{
		//实例方法中操作的可以是实例变量,也可以是类变量
		System.out.println("ParentClass的getName()方法被调用了!");
		return this.name;
	}

	//final方法,将ParentClass的年龄减1
	public final int getPreviousAge()
	{
		System.out.println("ParentClass的getPreviousAge()方法被调用!");
		return --age;
	}
}

class ChildClass extends ParentClass
{
	public static String classVar = "子类的字符串类变量";
	public int age = 25;//实例变量,ChildClass的年龄,在ParentClass类是static的
	public String name = "ChildClass";//实例变量,ChildClass的名字
	

	//静态方法,获取ChildClass的类别
	public static String getClassVar()
	{
		//静态方法中操作的只能是类变量,静态变量
		System.out.println("ChildClass的getClassVar()方法被调用!");
		return classVar;
	}

	//静态方法,获取父类的类别
	public static String getParentVar()
	{
		//通过类名加“.”访问父类被隐藏的类变量
		return ParentClass.classVar;
	}
	
	//实例方法,获取ChildClass的名字
	public String getName()
	{
		System.out.println("ChildClass的getName()方法被调用!");
		return this.name;
	}

	//实例方法,获取父类的名字
	public String getParentName()
	{
		//通过super关键字父类中被隐藏的实例变量
		return super.name;
	}

	//实例方法,获取父类的年龄
	public int getParentAge()
	{
		return ParentClass.age;
	}
}

/*
1.同名的实例方法被覆盖,同名的静态方法被隐藏。
	Child类的getName()实例方法覆盖了Parent类的getName()实例方法;
Child类的getClassVar()静态方法隐藏了Parent类的getClassVar()静态方法。

2.隐藏和覆盖的区别在于:子类对象转换成父类对象后,能够访问父类被隐藏
的变量和方法,而不能访问父类被覆盖的变量和方法。
	把child对象转换成Parent类的对象parent时,不能访问parent的getName()实例方法;
	把child对象转换成Parent类的对象parent后,能够访问Parent的getClassVar()静态方法。

3.子类若需要访问父类中被隐藏的实例变量,需要使用super关键字。
	Child类的getParentName()方法中就使用super.name访问Parent类的name实例变量。
	
4.子类若需要访问父类中被隐藏的类变量,需要使用父类的名字加点“.”来访问。
	Child类的getParentAge()方法使用了ParentClass.age访问Parent类的age静态变量。

*/