黑马程序员-面向对象(上)--继承、实现及多态

---------------------- android培训、java培训、期待与您交流! ----------------------

1.面向对象的概念:

面向对象程序设计Object-oriented programming,缩写:OOP),指一种程序设计范型,同时也是一种程序开发的方法。对象指的是的集合。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性。

2.面向对象的特征:

2.1封装

封装(encapsulation):是指隐藏对象的属性和实现细节,但是对外提供公共访问方式,它的好处是将变化隔离,便于作用,提高重用性和安全性。它的原则是将不需要对外提供的内容都隐藏起来,把属性都隐藏,提供公共访问方法对其访问。例如将人的年龄私有化以后,类以外即使建立了对象也不访问,但是人应该有年龄,是需要在类中提供相应访问年龄的方式。注意:私有仅仅是封装的表现形式,之所以提供访问方式,就因为在访问方式中加入了逻辑判断语句,对访问的数据进行操作。这样就提高了代码的健壮性。

     封装是一种OOP原则,它是保护需要确保安全的对象部分的一种机制,只暴露可以安全暴露的部分就可以了。我们的电脑就是一个很好封装的例子,电脑里面有成千上万个电子元器件,它们一起构成了可以为我们工作和生活提供方便的部件。但是这些部件不并暴露给我们,因此制造商就把它们包装在一个不容易破碎的外壳里面。在程序开发中,在类的内部有许许多多的变量用来保存临时的值,以及执行相关任务的方法。我们可以将这些变量和那些方法隐藏起来,因为允许访问它们会破坏编码/解码的安全性。另外,暴露太多的东西会使这个类使用起来更加困难。实际上封装是一种很强大的特性。
      java是通过访问控制来进行封装的,访问控制则是由修饰符进行管理的,Java提供了4种控制修饰符:publicprotectedprivate、默认访问。访问修饰符可以用到类或者类成员中。

2.2继承

 继承(inheritance):继承是面向对象编程的一项非常重要的特性。它使得代码在OOP语言中都可以进行扩展,扩展一个类也称做继承或者子类化。是Java中,默认所有类都是可扩展的,但是可以用final关键字阻止被子类化。它是子父类之间的关系,使用extends关键字来实现子类继承父类的。Java只支持单继承,不支持多继承即一个类只能有一个父类,不可以有多个父类。
    继承提高代码的利用性,让类与类之间产生了关系,才有了下面所说的多态的特性。当然,千万不要为了获取其它类的功能而简化代码的书写而使用继承,必须是类与类之前具有所属关系才能实现继续。

2.2.1函数重载和函数覆盖:

2.2.1.1函数的重载(Overload是指实现类似功能的多个函数,其函数的名称是一样的,只是参数不同,其返回值可以相同,也可以不同。它的好处在于不用为了对不同的参数个数和类型而重新写另一个函数,这样增加了程序的可读性,同时优化了程序的设计。什么时候用重载呢?当定义的功能相同,但参与运算的未知内容不同,那么这时就可以定义一个函数名称以表示其功能,它方便阅读,而通过参数列表的不同来区分不同的同名函数。
注:返回类型不能作为区分函数的标志
2.2.1.2函数的覆盖(Override):当子类出现和父类一模一样的函数时,子类对象调用调用该函数就会运行子类函数中的内容,如同父类函数被覆盖一样,也称为重写或复写。函数的覆盖实际上就是子父类之间的继承关系,当子类继承父类时,它也继承了父类中的方法和属性,对于从父类继承来的方法,可以对其进行扩展,就是子类要沿用父类中的功能,但是内容不一样时,我们就可以覆盖父类中的方法,来实现自己的要求。覆盖很简单,举个例子就能明白了,当父类中有一个方法a()时,继承它的子类也有方法a(),这就叫做覆盖。父类中的私有方法不能被覆盖。在子类覆盖方法中,继续使用被覆盖的方法可以通过super.函数名获取。覆盖的应用在哪里呢?当子类需要父类的功能时,而功能主体子类有自己的特有内容,这样就可以复写父类中的方法,即沿袭了父类的功能,又定义了子类的特有内容。
注:子类方法权限一定要大于等于父类方法的权限,而且静态只能覆盖静态。

2.2.2继承时构造函数特点:

2.2.2.1this、super、fianl关键字和构造函数
this和super关键字:
superthis的用法相像

this代表本类对象的引用
super代表父类的内存空间的标识。
当子父类出现同名成员时,可以用super进行区分。
子类要调用父类构造函数时,可以使用super语句。
final关键字:
final可以修饰类,方法,变量。

final修饰的类不可以被继承。
final修饰的方法不可以被覆盖。
final修饰的变量是一个常量。只能被赋值一次。
内部类只能访问被final修饰的局部变量。
构造函数:
特点:

1.函数名与类名相同
2.不用定义返回类型,括号中的参数可以没有,也可以有多个。
3.不可以写return语句
4.构造函数总是伴随着new操作一起被调用。
5.细节:当一个类中没有定义构造函数时,那么系统会默认给该类加入一个空参数的构造函数,即:类名(){}。但当类中自定义了构造函数后,默认的构造函数就不存在了。也就是说,每一个类中一定含有一个构造函数。
作用:给对象进行初始化
构造函数与一般函数的区别:运行上不同(写法也不一样)
注:一般函数是不能调用构造函数的,因为一般函数中不能定义this,而构造函数中可能存在this。
2.2.2.2子父类构造函数关系:

1.子类的所有的构造函数,默认都会访问父类中空参数的构造函数。
因为子类每一个构造函数内的第一行都有一句隐式super();
2.当父类中没有空参数的构造函数时,子类必须手动通过super语句形式来指定要访问父类中的构造函数。
当然:子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。
3.子类中至少会有一个构造函数会访问父类中的构造函数。
4.父类也有默认的super();,其父类为object
5.this()和super();不能同在一个构造函数中,因为它们都必须在第一行,这是因为初始化动作。
2.2.3接口和抽象类:

2.2.3.1接口:初期理解,它可以是一个特殊的抽象类。当抽象类中的方法都是抽象的时候,那么该类可以通过接口的形式来表示,这里要注意class是用来定义类的,而interface是用来定义接口的。相对于抽象类而言,接口是更纯粹的抽象类,它的所用方法都没有提供任何实现,只是给出方法的声明。它声明的方法只有返回类型、方法名和方法参数,但是没有函数体。这些方法都是public 的,即使不声明为public ,它默认的也是public。接口一旦被实现,就像普通类一样使用了,但是必须实现其声明的全部方法。另外接口可以定义属性,也可以为属性赋初使值。Java提供了interface来创建一个接口。下面是一个接口定义的示例:
interface Shape{ //通过关键字声明接口 
String shapetype = "hello"; 
int number = 1000; 
public void draw(); 
public void setColor(); 
}


:接口中觉定义有常量和抽象方法。接口的成员都有固定的修饰符,常量是:public static final。方法是:public abstract。接口中的成员都是public的。
接口是不可以创建对象的,因为有抽象方法。需要被子类实现,子类对接口中的抽象方法全部覆盖后,子类才可以实例化。否则子类是一个抽象类。

注:接口可以被类多实现,它是对多继承不支持的转换形式。java支持多实现。格式就是:interface {},接口与接口之间可以有继承的关系

2.2.3.2抽象类:抽象是一种看不懂的东西,当多个类中出现了相同的功能,但是功能主体不同,这时可以向上抽取,但是只抽取功能定义,而不抽取功能主体。抽象就是从多个事物中将共性的,本质的内容抽取出来。抽象类和一般类没有太大的不同,该如何描述事物,就如何描述事物,只不过,该事物出现了一些看不懂的东西。这些不确定的部分,也是该事物的功能,需要明确出现。但是无法定义主体。通过抽象方法来表示。抽象类比一般类多个了抽象函数。就是在类中可以定义抽象方法。抽象类不可以实例化。特殊:抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象。
      抽象类的特点:抽象方法和抽象类必须声明abstract关键字来修饰。
         抽象方法只有方法声明,没有方法主体,定义在抽象类中。
         格式为:修饰符 abstract返回值类型 函数名(参数列表)
         抽象类不可以被实例化,也就是不可以用new来创建对象。原因如下:抽象类是具体事物抽象出来的,本身不是具体的,没有对应的实例,例如犬科是一个抽象的概念,真正存在的是狗和狼。而且即使抽象类创建了对象,调用抽象方法也没有意义。
          抽象类通过其子类进行实例化,而子类需要覆盖掉抽象类中的所有的抽象方法后,才可以创建对象,否则该子类也是抽象类。

abstract和哪些关键字不能共存:
final:被final修饰的类不能有子类。而被abstract修饰的类一定是一个父类。
private:抽象类中的私有的抽象方法,不被子类所知,就无法被复写。而抽象方法出现的就是需要被复写。
 static:如果static可以修饰抽象方法,那么连对象都省了,直接类名调用就可以了。可是抽象方法运行没意义。
抽象类中是否有构造函数:有,抽象类是一个父类,要给子类提供实例的初始化。
以下例子简单描述下抽象类用法:

abstract class Employee 
{ 
private String name; //定义员工的姓名 
private String id; //定义员工工号 
private double pay ; //定义员工工资 
Employee(String name,String id,double pay) //定义带参的构造函数 
{ 
this.name = name; 
this.id = id; 
this.pay = pay; 
} 
public abstract void work(); //定义抽象方法 
} 
class Manager extends Employee //经理继承员工,因为经理也是员工的一员 
{ 
private int bonus; //定义资金 
Manager(String name,String id,double pay,int bonus) //复写构造函数 
{ 
super(name,id,pay); //调用父类中的构造函数 
this.bonus = bonus; 
} 
public void work() //复写抽象方法,定义更详细的功能主体 
{ 
System.out.println("manager work"); 
} 
}


2.2.3.3接口和抽象类异同点
相同:
1都可以在内部定义抽象方法。
2通常都在顶层。
3都不可以实例化,都需要子类来实现。
不同点:
1抽象类中可以定义抽象方法和非抽象方法,
    而接口中只能定义抽象方法。
2接口的出现可以多实现。
    抽象类只能单继承。
    也就是说:接口的出现避免了单继承的局限性。
3继承和实现的关系不一致。

2.3多态

多态(polymorphism):可以理解为事物存在的多种体现形态。它使一个对象能够决定,在接收到一个方法调用时,该调用哪个实现。

  多态的体现:父类的引用指向了自己的子类对象,父类的引用也可以接收自己的子类对象。
  多态的前提:必须是类与类之间关系,要么继承,要么实现。通常还有一个前提:存在覆盖。
  多态的好处:多态的出现大大的提高的程序的扩展性和后期的可维护性。
  多态的弊端:提高了扩展性,但是只能使用父类的引用访问父类中的成员。
  多态出现代码的特点:
     Animal a = new Cat();它进行了类型提升,向上转型。如果想相调用Cat的特有方法时,要怎么操作呢?就要强制将父类的引用转成子类类型,这是向下转型。我们千万不要这样做,就是把父类对象转成子类类型,例如:{Animal a= new Animal();Cat c=Cat(a);c.catchMouse();} 我们能转换的是父类引用指向了自己的子类对象时,该引用可以被提升,也可以被强制转换。多态自始至终都是子类在做着变化。用来指定某一个对象是否为某种指定的类型,我们用关键字instanceof来检验,它通常用在if语句中,由于子类是父类的一种类型,因此下面的if()语句(这里的ChildParent的一个子类)将返回true
                              Child child = new Child();
                              if(child instanceof Parent)     //运算结果为true
     成员函数的特点:编译时,要查看引用变量所属的类中是否有调用的成员;在运行的时候要查看对象所属的类是否有所调用的成员。简单说就是成员函数在多态调用时,编译看左边,运行看右边。
     成员变量的特点,无论编译和运行都看左边。
     静态成员函数的特点,无论编译和运行都看左边。
以下一个小事例来说明继承和多态的特点:

public class Fu {

	/**
	 * @param args
	 */
	
	
	
	Fu(){
		System.out.println("Fu Noargs is run");
	}
	 Fu(int number){
		 System.out.println("Fu"+number+"is run");
	 }
	public void print(int i){  
	           System.out.println("您调用的为父类中的函数,输入整数为父:"+i);  
	}  
	public void print(int i,int j){  
	           System.out.println("您调用的为父类中的函数,输入整数为:"+i+j); // 该类中 print(int i)和print(int i,int j) 方法即是重载关系
	 }
}

public class Demo extends Fu{

	/**
	 * @param args
	 */
	
		
		public Demo(){
			
			super(1);//在此指定调用父类中带参数的Fu(int number)函数,若此句不写,则默认隐藏为super(),调用空参的父类构造函数
			
			System.out.println("Demo Noargs is Run");
		}
		public Demo(String str){
			this();//若此句不写,则默认隐藏为super(),调用空参的父类构造函数
			System.out.println(str);
		}
		public void print(int i){  
	              System.out.println("the number is:"+i);  
	     }//此方法与Demo中print(int i)的关系即为覆盖
		public void print(String str){
			System.out.println("此方法为子类特有方法,无覆盖,你输入的字为"+str);
		}
		public static void main(String[] args){
			Fu fu=new Demo("Test1");//父类引用指向子类对象
			Demo demo=new Demo();
		    fu.print(2);//print(int i)为子类覆盖父类中print(int i)方法,故此调用子类中print(int i)方法
		    fu.print(3, 4);//print(int i,int j) 为父类中方法,子类没有覆盖,故调用父类中的print(int i,int j)
//		    fu.print("Erro");//父类引用指向子类对象,后编译看左边,无法调用子类特有方法,故编译无法通过
		    demo.print("specific");// 子类对象调用自己特有方法
		
	/*以上运行结果为:
	 * Fu1is run
		Demo Noargs is Run
		Test1
		
		Fu1is run
		Demo Noargs is Run
		
		the number is:2
		您调用的为父类中的函数,输入整数为:34
		此方法为子类特有方法,无覆盖,你输入的字为specific
	 
	 **/	    
		    
		}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值