Day1---继承(1)

1. 继承的基本语法

java语言中使用extends关键字表示继承。子类继承父类的哪些东西呢?分两种情况:
(1)如果子类和父类位于同一个包时:子类继承父类中public、protected、default访问级别的成员变量和成员方法;
(2)如果父类和子类不在同一个包时:子类继承父类中public、protected访问级别的成员变量和成员方法。

java不支持多继承,一个类只能继承一个类,所有java类都直接或者间接继承java.lang.Object类。假如在定义一个类时,没有使用extends关键字,那么这个类直接继承Object类。

2. 方法重载(Overload)

有时候,类的一种功能有多种实现方式,到底采用哪种实现方式,取决于调用者给定的参数。
对于类的方法(包括从父类继承来的方法),如果有两个方法的方法名相同,但参数不一样,那么一个方法是另一个方法的重载方法。
重载方法必须满足以下条件:

- 方法名相同
- 方法的参数类型、顺序、个数至少有一个不一样
- 方法的返回类型可以不相同
- 方法的修饰符可以不相同

在同一个类中不允许定义两个方法,方法名和参数都完全相同,即使访问权限和方法返回值类型不一致,编译还会出错。因为java虚拟机在运行时无法决定到底执行哪个方法。构造方法、类方法、final方法均可以重载。

class Dog{}
class Cat{}
class Fish{}
class Animal{
	public void eat(Cat cat)
	{
		System.out.println("我是小猫,我在吃鱼");
	}
	public void eat(Dog dog)
	{
		System.out.println("我是小狗,我在吃肉");
	}
	public void eat(Fish fish)
	{
		System.out.println("我是小鱼,我在吃猫");
	}
	public static void main(String args[])
	{
		Animal animal=new Animal();
		Dog dog=new Dog();
		Cat cat=new Cat();
		Fish fish=new Fish();
		
		/*
		以下三个都是执行animal对象的eat方法,但具体执行哪个方法,取决于方法的参数。
		*/
		animal.eat(dog);
		animal.eat(cat);
		animal.eat(fish);
	}
}

3. 方法覆盖(Override)

如果在子类中定义的一个方法,其名称、返回类型、参数刚好与父类中的一个方法完全匹配。那么子类方法覆盖了父类方法。
方法覆盖必须满足以下多种约束。

  • 子类方法的名称、返回值类型、参数必须完全与父类方法的名称、返回类型和参数一致,否则编译错误;但是允许子类覆盖父类的方法,然后在子类中再对该方法进行重载。如下代码是合法的。

    class Fish extends Animal{
    	public void eat(Fish fish)//覆盖父类的eat(Fish fish)方法
    	{
    		System.out.println("我是小鱼儿子,我在吃猫");
    	}
    	public String eat()//重载子类中的eat(Fish fish)方法
    	{
    		return null;
    	}
    }
    class Animal{
    	public void eat(Fish fish)
    	{
    		System.out.println("我是小鱼爸爸,我在吃猫");
    	}
    }
    
  • 子类方法不能缩小父类方法的访问权限,否则编译错误。

    Base base=new Sub();
    base.method();
    

    上述代码中定义了一个Base类型的引用变量base,引用Sub类型的实例。base调用method方法时,会优先执行Sub类中的method方法,一旦Sub类中没有该方法,再执行父类中的method方法。如果子类存在method方法,且方法的访问权限为private,可能会导致java虚拟机无法访问该方法。

  • 子类方法不能抛出比父类更多的异常。子类方法抛出的异常必须和父类方法抛出的异常相同,或者子类方法抛出的异常类是父类方法抛出的异常类的子类。否则,会编译出错。之所以这样设计,是防止调用子类方法时抛出更多的异常,无法被捕获,导致程序中断。

  • 方法覆盖只存在于子类和父类(或者直接父类和间接父类)中,同一个类中的方法只能被重载,不能被覆盖。

  • 父类的静态方法不能被子类覆盖为非静态方法。因为静态方法属于类,而不是属于这个类的某个实例对象,所以父类的静态方法,在被子类继承之后,也属于子类,所以子类中不可以再写一个非静态方法覆盖原有静态方法。否则编译出错。

  • 父类的非静态方法不能被子类覆盖为静态方法。否则编译出错。

  • 子类可以定义和父类的静态方法同名的静态方法,以便在子类中隐藏父类的静态方法。编译时,子类中定义的静态方法也必须满足和方法覆盖一样的约束:参数一致、返回值一致、方法名一致、不能缩小父类方法的访问权限、不能抛出更多的异常。

    public class Base{
    	static int method(int a)throws BaseException{
    		return 0;
    	}
    }
    public class Sub extends Base{
    	public static int method(int a)throws SubException{
    		return 1;
    	}
    }
    

    子类覆盖父类的实例方法和子类隐藏父类的静态方法,两者区别在于:运行时,java虚拟机把静态方法和所属的类绑定,实例方法和所属的实例绑定。

    class Test332 extends Animal{
    	void eat()
    	{
    		System.out.println("子类实例方法");
    	}
    	static void walk()
    	{
    		System.out.println("子类静态方法");
    	}
    	
    	public static void main(String args[])
    	{
    		Animal a=new Test332();
    		a.eat();//子类实例方法
    		a.walk();//父类静态方法
    		
    		Test332 b=new Test332();
    		b.eat();//子类实例方法
    		b.walk();//子类静态方法
    	}	
    }
    class Animal{
    	void eat()
    	{
    		System.out.println("父类实例方法");
    	}
    	static void walk()
    	{
    		System.out.println("父类静态方法");
    	}
    }
    

    引用变量a、b都是引用子类的实例,在执行实例方法eat时,都是执行子类定义的eat方法,因为父类的eat方法被覆盖。但a被声明为父类类型的引用变量,所以在执行静态方法walk时,执行的是父类中定义的方法,而b被声明为子类类型的引用变量,所以执行子类静态方法。

  • 父类的私有方法不能被子类覆盖。子类方法覆盖父类方法的前提是:子类必须继承父类的方法,而private方法只能被当前类访问。

    class Test332 extends Animal{
    	void eat()
    	{
    		System.out.println("子类实例方法");
    	}
    	public static void main(String args[])
    	{
    		Test332 b=new Test332();
    		b.eat();//子类实例方法
    		b.walk();//父类实例方法
    	}
    }
    class Animal{
    	private void eat()
    	{
    		System.out.println("父类实例方法");
    	}
    	void walk()
    	{
    		eat();
    	}
    }
    

    引用变量b调用walk方法时,会执行父类中的eat方法,因为父类eat方法时private的,未被子类覆盖。如果将private去掉,则引用变量b调用walk方法时,会执行子类中的eat方法,因为父类eat方法已经被覆盖。

  • 父类的抽象方法可以被子类通过两种途径覆盖。一是子类实现父类的抽象方法,二是子类重新声明父类的抽象方法。且父类的非抽象方法可以被覆盖为抽象方法。

4. 方法覆盖和方法重载的异同

相同点:

  • 都要求方法同名
  • 都可以用于抽象方法和非抽象方法之间

不同点:

  • 方法覆盖要求返回值类型、参数都一致;方法重载对返回值类型没要求,却要求参数一定不能一致
  • 方法覆盖只能用于子类覆盖父类的方法;方法重载则用于同一个类的所有方法(包括从父类继承的方法)
  • 方法覆盖对访问权限和抛出的异常有特殊要求;方法重载则没有要求
  • 父类的一个方法只能被子类覆盖一次,而方法重载可以在一个类中进行多次
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值