类和对象(2)

包(package):其实就是存放类的文件夹,一般命名为(例子:com.baidu.demo1),其目的是为了把不同的类区分开来,以免文件名冲突带来不必要的麻烦,导包一般使用import(例子:import java.util.Date),或者使用某个方法时IDEA会自动导包。

面向对象编程语言第二大特性:继承( 被继承的类,我们称为 父类/基类/超类。而继承自其他类的新类,我们称为 子类/派生类。class A extends B(其中A为子类,B为父类)【为了代码的复用,不要有冗余的代码】

继承表示 is - a 语义,   猫 "是" 一种动物
class Animal { 
 public Animal(String name) { 
 this.name = name; 
 } 
} 


class Cat extends Animal { 
 public Cat(String name) { 

 // 使用 super 调用父类的构造方法. 
 super(name); 
 } 

子类会继承父类的属性(成员变量)和方法(除构造方法构造方法存在的意义就是为了帮助类去创建对象,因此可以带参数或者不带参数,如果不写构造方法那么系统会默认生成一个不带参数的构造方法

子类构造首先需要构造父类,调用父类的构造方法,帮助父类进行构造;

1.super.func()    调用父类的方法

2.super.data      调用父类的属性

3.super()           调用父类的构造方法[必须放在第一行]

Java 中对于字段和方法共有四种访问权限:

  1. private:类内部能访问, 类的外部不能访问;
  2. 默认/default: 类内部能访问, 同一个包中的类可以访问, 其他类不能访问;
  3. protected: 类内部能访问, 子类和同一个包中的类可以访问, 其他类不能访问;
  4. public:类内部和类的调用者都能访问。

我们希望类要尽量做到 "封装",即隐藏内部实现细节, 只暴露出必要的信息给类的调用者。因此我们在使用的时候应该尽可能的使用 比较严格 的访问权限,例如如果一个方法能用 private,就尽量不要用 public 。

final 关键字,修饰一个变量或者字段的时候,表示 该值为常量 (不能修改);final也能修饰类,表示被修饰的类就不能被继承。

我们平时使用的 String 字符串类, 它的源码是用 final 修饰的,表示为最终类,不能再被继承。

组合表示 has - a 语义,     学校 "包含/有" 学生和教师
public class Student { 
 ... 
} 

public class Teacher { 
 ... 
} 

public class School { 
 public Student[] students; 
 public Teacher[] teachers; 
} 

面向对象编程语言第三大特性:多态(1.向上转型-->2.方法重写-->3.动态绑定

什么是多态?

字面理解:同一对象的不同形态;

程序分析:父类(或接口)的引用指向子类(或具体实现类)的对象,且两者间有同名的重写方法,此时如果通过父类引用来调用这个方法的时候,会发生动态绑定,从而调用子类中的该方法,这个过程就叫做运行时多态,简称多态。

1.向上转型

一个父类 (Animal) 的引用,指向一个子类 (Bird) 的对象,这种写法称为 向上转型。

Animal bird = new Bird("豆豆"); 

为啥叫 "向上转型" ?
在面向对象程序设计中,针对一些复杂的场景(很多类,很复杂的继承关系),程序员会首先画UML 图的方式来整理清楚类之间的关系。此时父类通常画在子类的上方,所以我们就称为 "向上转型" ,表示往父类的方向转。

2.方法重写

方法名、参数个数和类型、返回值完全相同,只能用在继承关系当中,父类的方法只能被子类重写一次,权限 >= 父类,这样的两个方法构成重写。

public class Animal { 
 (default) void eat(String food) { 
 ... 
 } 
}


public class Bird extends Animal { 

 @Override
 public void eat(String food) { 
 ... 
 } 
} 

重载和重写(private和static修饰的方法不支持重写):

相同点:

(1)要求方法名相同;
(2)都可以用于抽象方法和非抽象方法之间。

不同点:

(1)重写要求参数必须相同;而方法的重载要求参数签名必须不同。
(2)重写要求返回类型必须相同;而方法重载对此没有限制。
(3)重写只能用于子类重写父类的方法;而方法的重载用于同一个类的所有方法(包括从父类中继承的方法)。
(4)重写对方法的访问权限和抛出的异常有特殊要求;而方法的重载对此没有任何限制。
(5)父类的一个方法只能被子类重写一次;而一个方法在所在的类中可以被多次重载。
 

3.动态绑定

调用类中的某个方法时,实际执行了哪段代码 (是父类方法的代码还是子类方法的代码) , 要看究竟这个引用指向的是父类对象还是子类对象。这个过程是程序运行时决定的(而不是编译期),因此称为 动态绑定。

 
 Animal animal1 = new Animal("豆豆"); 
 animal1.eat("谷子"); 

 Animal animal2 = new Bird("扁扁"); 
 animal2.eat("谷子"); 

 

多态代码示例:

//画画(父类)
class Shape { 
 public void draw() { 
 } 
} 

//画圆形(子类)
class Cycle extends Shape { 
 @Override 
 public void draw() { 
 System.out.println("○"); 
 } 
} 


//画方块(子类)
class Rect extends Shape { 
 @Override 
 public void draw() { 
 System.out.println("□"); 
 } 
} 


//画花型(子类)
class Flower extends Shape { 
 @Override 
 public void draw() { 
 System.out.println("♣"); 
 } 
} 



// Test.java (测试类)


public class Test { 
 public static void main(String[] args) { 
     Shape shape1 = new Flower(); 
     Shape shape2 = new Cycle(); 
     Shape shape3 = new Rect(); 
     drawMap(shape1); 
     drawMap(shape2); 
     drawMap(shape3); 
 } 

 // 打印单个图形
 public static void drawShape(Shape shape) { 
     shape.draw(); 
 } 
} 

使用多态的好处是什么?

1) 多态是封装的更进一步:封装是让类的调用者不需要知道类的实现细节;多态让类的调用者连这个类的类型是什么都不必知道。

2) 能够降低代码的 "圈复杂度",避免使用大量的 if - else使得代码难以阅读。

3) 可扩展能力更强,如果要新增一种新类,使用多态的方式代码改动成本也比较低(对于类的调用者来说,只要创建一个新类的对象就可以了, 改动成本非常低。而对于不用多态的情况,就要对 if - else 进行一定的修改,改动成本非常高。


向下转型:

向下转型(使用的不多)
Animal animal = new Cat("小猫"); 


if (animal instanceof Bird) { 
 Bird bird = (Bird)animal; 
 bird.fly(); 
}

instanceof   可以判定一个引用是否是某个类创建的对象。

super与this的区别:

super 表示 由子类访问父类的属性或方法;

this    表示  访问本类中的属性或方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值