继承

1.1   类和类之间的常见关系。

1:既然继承是描述类和类之间的关系,就需要先来了解类和类之间的常见关系

1.1.1   现实生活的整体与部分

举例说明

1:现实生活

1:学生   是人

2:狗     是动物

3:球队 包含 球员 整体与部分的关系,部分可以删除和增加

4:笔记本包含 cpu 整体与部分的关系,部分不可以删除和增加

5:航母编队 包含(航母 护卫舰 驱逐舰 舰载机 核潜艇)

1.1.2   java中的类与类关系

java中的类关系

1:is a 关系 (学生是人)

2:has a 整体与部分

 class Person{
String name;
int age;
Address add; Person(){ }
Person(String name,int age,Address add){ this.name=name;
this.age=age;
this.add=add; } void speak(){
System.out.println("姓名:"+name+" 年龄:"+age+" "+add.print());
}
}
class Address{
String country;
String city;
String street; Address(){ }
Address(String country,String city,String street){
this.country=country;
this.city=city;
this.street=street;
} String print(){
return "地址:"+country+" "+"城市:"+city+" 街道;"+street;
}
}
class Demo3{ public static void main(String[] args){ Address add=new Address("中国","广州","棠东东路");
Person p=new Person("jack",27,add);
p.speak(); System.out.println();
}
}

继承

1:描述一个学生类

1:姓名年龄学号属性,学习的方法

2:描述一个工人类

1:姓名年龄工号属性,工作的方法

3:描述一个人类

1:姓名年龄属性,说话的方法。

  4:发现学生类和人类天生有着联系,学生和工人都是人。所以人有的属性和行为学生和工人都会有。出现类代码重复

 class Person {
String name;
int age; // 静态变量(类变量)对象和对象之间的代码重复使用静态变量
static String country = "CN"; Person() { } void speak() {
System.out.println(name + ":哈哈,我是人!!!");
} } // 让学生类和人类产生关系,发现学生is a 人,就可以使用继承
class Student { String name;
int age; Student() { } void study() {
System.out.println("姓名:" + name + "年纪:" + age + ":好好学习");
}
} class Worker {
String name;
int age; void work() {
System.out.println(name + ":好好工作,好好挣钱。");
} } class Demo1 { public static void main(String[] args) {
Student s = new Student();
s.name = "jack";
s.age = 20;
s.study(); Worker w = new Worker();
w.name = "rose"; w.work();
}
}

5:问题:

1:如果没有继承,出现类和类的关系无法描述

2:如果没有继承,类和类之间有关系会出现类和类的描述代码的重复。

继承特点

1:描述类和类之间的关系

2:降低类和类之间的重复代码

  1:降低对象和对象之间的代码重复使用静态变量

2:降低类和类之间的代码重复使用就继承

extends关键字

继承使用extends关键字实现

1:发现学生是人,工人是人。显然属于is a 的关系,is a就是继承。

2:谁继承谁?

学生继承人,发现学生里的成员变量,姓名和年龄,人里边也都进行了定义。有重    复代码将学生类的重复代码注释掉,创建学生类对象,仍然可以获取到注释的成员。这就是因为继承的关系,学生类(子类)继承了人类(父类)的部分

 class Person {
String name;
int age; // 静态变量(类变量)对象和对象之间的代码重复使用静态变量
static String country = "CN"; Person() { } void speak() {
System.out.println(name + ":哈哈,我是人!!!");
} } // 让学生类和人类产生关系,发现学生is a 人,就可以使用继承
class Student extends Person { Student() { } void study() {
System.out.println("姓名:" + name + "年纪:" + age + ":好好学习");
}
} class Worker extends Person { void work() {
System.out.println(name + ":好好工作,好好挣钱。");
} } class Demo1 { public static void main(String[] args) {
Student stu = new Student();
stu.name = "jack";
stu.age = 20;
stu.study();
stu.speak();
System.out.println(stu.country);
System.out.println(Student.country); Worker worker = new Worker();
worker.name = "rose";
System.out.println(worker.country);
worker.work();
worker.speak(); System.out.println();
}
}

继承细节;

1:类名的设定,被继承的类称之为父类(基类),继承的类称之为子类

2:子类并不能继承父类中所有的成员

1:父类定义完整的成员 静态成员,非静态,构造方法。静态变量和静态方

法都可以通过子类名.父类静态成员的形式调用成功。

2:所有的私有成员不能继承,private修饰的成员。

3:构造函数不能被继承

3:如何使用继承

1:不要为了使用继承而继承。工人和学生都有共性的成员,不要为了节省代

码,让工人继承学生。

 /*
如何使用继承:验证是否有 is a 的关系
例如:学生是人, 小狗是动物
注意:不要为了使用某些功能而继承,java只支持单继承
*/
class DK { void Ip4S() {
System.out.println("好玩");
}
} class BGir extends DK { } class Demo { public static void main(String[] args) { new BGir().Ip4S(); }
}

super关键字

1:定义Father(父类)类

1:成员变量int x=1;

2:构造方法无参的和有参的,有输出语句

2:定义Son类extends Father类

1:成员变量int y=1;

2:构造方法无参和有参的。有输出语句

1:this.y=y+x;

3:创建Son类对象

Son son=new Son(3);

System.out.println(son.y); //4

 class Father {
int x = 1; Father() {
System.out.println("这是父类无参构造");
} Father(int x) { this.x = x;
System.out.println("这是父类有参构造");
} void speak() {
System.out.println("我是父亲");
}
} class Son extends Father {
int y = 1; Son() {
System.out.println("这是子类的无参构造");
} Son(int y) { this.y = y + x;
System.out.println("这是子类的有参构造");
} void run() {
super.speak(); // 访问父类的函数
System.out.println("我是儿子");
}
} class Demo6 { public static void main(String[] args) {
Son s = new Son(3);
System.out.println(s.y);//
}
}

  4:子类对象为什么可以访问父类的成员。

1:this.y=y+x;有一个隐式的super super.x

  5:super关键字作用

1:主要存在于子类方法中,用于指向子类对象中父类对象。

2:访问父类的属性

3:访问父类的函数

4:访问父类的构造函数

  6:super注意

   this和super很像,this指向的是当前对象的调用,super指向的是当前调用对象的父类。Demo类被加载,执行main方法,Son.class加载,发现有父类Father类,于是Father类也加载进内存。类加载完毕,创建对象,父类的构造方法会被调用(默认自动无参),然后执行子类相应构造创建了一个子类对象,该子类对象还包含了一个父类对象。该父类对象在子类对象内部。this super只能在有对象的前提下使用,不能在静态上下文使用。

  子类的构造函数默认第一行会默认调用父类无参的构造函数,隐式语句

    super();

1:父类无参构造函数不存在,编译报错。

 Son(int y) {
//super();隐式语句
this.y = y + x;
System.out.println("这是子类的有参构造");
}

  子类显式调用父类构造函数

  在子类构造函数第一行通过super关键字调用父类任何构造函数。如果显式调用父类构造函数,编译器自动添加的调用父类无参数的构造就消失。构造函数间的调用只能放在第一行,只能调用一次。super() 和this()不能同时存在构造函数第一行。

  

 Son(int y) {
super(y);// 子类显式调用父类构造函数
this.y = y + x;
System.out.println("这是子类的有参构造");
} Son(int y) {
this(); //不能同时存在构造函数第一行
super(y);
this.y = y + x;
System.out.println("这是子类的有参构造");
}

super思考

如果开发者自定义了一个类,没有显示的进行类的继承,那么该类中成员函数是否可以使用super关健健字?可以使用,继承了Object类,Object类是所有类的父类。

 class Demo7 {
public void print(){
System.out.println(super.toString());
}
public static void main(String[] args){
new Demo7().print();
System.out.println();
}
}

7:重写(Override)

1:定义Father类

1:姓名,吃饭方法,吃窝窝头。

2:定义Son类,继承Father

1:Son类中不定义任何成员,子类创建对象,仍然可以调用吃饭的方法。

2:父类的吃饭的方法,Son不愿吃。Son自己定义了吃饭的方法。

1:此时父类中有一个吃饭的方法,子类中有2个吃饭的方法,一模一样,只是方法体不一样。

2:一个类中两个函数一模一样,是不允许的。

1:编译运行,执行了子类的方法。

2:使用父类的方法,在子类方法中,使用super.父类方法名。

 class Father {
String name; void eat() {
System.out.println("吃窝窝");
}
} class Son extends Father { public void eat() { // 继承可以使得子类增强父类的方法
System.out.println("来俩小菜");
System.out.println("来两杯");
System.out.println("吃香喝辣");
System.out.println("来一根");
}
} class Demo8 { public static void main(String[] args) {
Son s = new Son();
//执行子类的方法
s.eat(); }
}

3:该现象就叫做重写(覆盖 override)

1: 在继承中,子类可以定义和父类相同的名称且参数列表一致的函数,将这种函数

称之为函数的重写.

4:前提

1:必须要有继承关系

5:特点

1:当子类重写了父类的函数,那么子类的对象如果调用该函数,一定调用的是重写过后的函数。

可以通过super关键字进行父类的重写函数的调用。

2: 继承可以使得子类增强父类的方法

6:细节

1: 函数名必须相同

2:参数列表必须相同

  3: 子类重写父类的函数的时候,函数的访问权限必须大于等于父类的函数的访

问权限否则编译报错

  4:子类重写父类的函数的时候,返回值类型必须是父类函数的返回值类型或该返回值类型的子类。不能返回比父类更大的数据类型: 如子类函数返回值类型是Object

1:定义 A B  C 类 B extends A

2:Father类中定义A getA();

3:Son 类中重写getA(); 方法,尝试将返回值修改为B,C ,Object

1:B编译通过

2:C 编译失败 ,没有继承关系

3:Object编译失败,比父类的返回值类型更大

1:定义 A B  C 类 B extends A

2:Father类中定义A getA();

3:Son 类中重写getA(); 方法,尝试将返回值修改为B,C ,Object

1:B编译通过

2:C 编译失败 ,没有继承关系

3:Object编译失败,比父类的返回值类型更大

 class A {

 }

 class B extends A {

 }

 class C {

 }
class Father {
String name; void eat() {
System.out.println("吃窝窝");
} // 定义一个函数,获取A类的对象,
A getA() {
return new A();
} } class Son extends Father { public void eat() { // 继承可以使得子类增强父类的方法
System.out.println("来两杯");
System.out.println("来俩小菜");
super.eat();
System.out.println("来一根");
} // B类是A类的子类
B getA() {
return new B();
}
} class Demo8 { public static void main(String[] args) {
Son s = new Son();
s.eat(); }
}

7:子类对象查找属性或方法时的顺序:

1:原则:就近原则。

如果子类的对象调用方法,默认先使用this进行查找,如果当前对象没有找到属性或方法,找当前对象中维护的super关键字指向的对象,如果还没有找到编译报错,找到直接调用。

8:重载和重写的不同

1:重载(overload):

1:前提: 所有的重载函数必须在同一个类中

2:特点:

函数名相同,参数列表不同,与其他的无关(访问控制符、返回值类型)

3:不同:

个数不同 、 顺序不同、 类型不同

2:重写(override):

1:前提: 继承

2:特点:

函数名必须相同、参数列表必须相同。

子类的返回值类型要等于或者小于父类的返回值

9:重写练习

描述不同的动物不同的叫法

1:定义动物类

有名字,有吃和叫的方法

2:定义狗继承动物重写父类吃和叫的方法

3:定义猫继承动物重写父类吃和叫的方法

 class Animal{
int x=1;
String name; void eat(){
System.out.println("吃东西");
}
void shout(){
System.out.println("我是动物");
}
} class Dog extends Animal{ void eat(){
System.out.println("啃骨头");
}
void shout(){
System.out.println("旺旺");
}
void eat(String food){
System.out.println("吃:"+food);
}
}
class Cat extends Animal{ void eat(){
System.out.println("吃老鼠");
}
void shout(){
System.out.println("喵喵");
}
} class Demo9{ public static void main(String[] args){
Dog d=new Dog();
d.shout();
d.eat(); Cat c=new Cat();
c.shout();
c.eat();
System.out.println();
}
}

instanceof 关键字

1:快速演示instanceof

 Person p=new Person();
System.out.println( p instanceof Person);

2:instanceof是什么?

1:属于比较运算符:

2:instanceof关键字:该关键字用来判断一个对象是否是指定类的对象。

3:用法:

对象  instanceof 类;

该表达式是一个比较运算符,返回的结果是boolea类型  true|false

注意:使用instanceof关键字做判断时,两个类之间必须有关系。

3:案例

定义一个功能表函数,根据传递进来的对象的做不同的事情,如果是狗让其看家,如果是猫让其抓老鼠

1:定义动物类

2:定义狗类继承动物类

3:定义猫类继承动物类

4:定义功能根据传入的动物,执行具体的功能

5:instanceof好处

1:可以判断对象是否是某一个类的实例

 package oop01;

 /*
instanceof
比较运算符
检查是否是类的对象
1:可以判断对象是否是某一个类的实例
用法
对象 instanceof 类; 案例
定义一个功能函数,根据传递进来的对象的做不同的事情
如果是狗让其看家,如果是猫让其抓老鼠
1:定义动物类
2:定义狗类继承动物类
3:定义猫类继承动物类
4:定义功能根据传入的动物,执行具体的功能
*/ class Animal { String name; void eat() {
System.out.println("吃东西");
} void shout() {
System.out.println("我是动物");
}
} class Dog extends Animal { void eat() {
System.out.println("啃骨头");
} void shout() {
System.out.println("旺旺");
} } class Cat extends Animal { void eat() {
System.out.println("吃老鼠");
} void shout() {
System.out.println("喵喵");
}
} class Demo11 { public static void main(String[] args) { Demo11 d = new Demo11(); // 对象 instanceof 类;
System.out.println(d instanceof Demo11); d.doSomething(new Dog());
d.doSomething(new Cat());
} // 定义一个功能函数,根据传递进来的对象的做不同的事情
// 如果是狗让其看家,如果是猫让其抓老鼠
// 对象 instanceof 类;
void doSomething(Animal a) {
if (a instanceof Dog) {
a.eat();
a.shout();
System.out.println("小狗看家");
} else if (a instanceof Cat) {
a.eat();
a.shout();
System.out.println("抓老鼠");
}
}
}
 byte[] bs = new byte[] { 1, 2, 3 };
int[] is = new int[] { 1, 2, 3 };
String[] ss = new String[] { "jack", "lucy", "lili" };
System.out.println(bs instanceof byte[]); // true
System.out.println(is instanceof int[]); // true
System.out.println(ss instanceof String[]); // true
// System.out.println(bs instanceof int[]); // 不可转换的类型

final关键字

 1:定义静态方法求圆的面积

2:定义静态方法求圆的周长

3:发现方法中有重复的代码,就是PI,圆周率。

1:如果需要提高计算精度,就需要修改每个方法中圆周率。

4:描述一个变量

1:方法都是静态的,静态只能访问静态,所以变量也定义为静态的。

public static double PI=3.14;

1:如果定义为public后,新的问题,类名.PI=300; 改变了PI的值。

    2:修改为private,修改为private后进行了封装,需要getset公共访问方法。

3:现有的知识不能解决这样的问题了。可以使用final

 class Demo12 {

     public static final double PI = 3.14; // 静态常量

     public static double getArea(double r) {
return PI * r * r;
} public static double getLength(double r) {
return PI * r * 2;
} public static void main(String[] args) { // Demo12.PI=300; 无法为最终变量 PI 指定值
System.out.println(Demo12.PI); } }

5:使用final

1:final关键字主要用于修饰类、类成员、方法、以及方法的形参。

2:final修饰成员属性:

1:说明该成员属性是常量,不能被修改。

public static final double PI=3.14;

1:public :访问权限最大

2:static :内存中只有一份

3:final  :是一个常量

4:常量名大写

5:必须初赋值。

2:使用类名.成员。修改该成员的值,报错。--常量不能被修改

1:基本数据类型,final使值不变

2:对象引用,final使其引用恒定不变,无法让其指向一个新的对象,但是对象自身却可以被修改。

3:该关键字一般和static关键字结合使用

1:常量可以优先加载,不必等到创建对象的时候再初始化。

4:final和static可以互换位置

5:常量一般被修饰为final

3:fianl修饰类:

1:该类是最终类,不能被继承。

1:将父类加final修饰,子类继承,就会报错。

        2:查看api文档发现String类是final的。Integer类也是final的

1:为了防止代码功能被重写

2:该类没有必要进行扩展

4:final修饰方法:

1:该方法是最终方法,不能被重写

      2:当一个类被继承,那么所有的非私有函数都将被继承,如果函数不想被子类继承并重写可以将该函数final修饰

3:当一个类中的函数都被修饰为final时,可以将类定义为final的。

 class Father2{
final void eat(){
System.out.println("eating....");
}
} class Son2 extends Father2{
//该方法是最终方法,不能被重写
void eat(){
System.out.println("eating....");
}
}
class Demo12 { public static void main(String[] args) { // Demo12.PI=300; 无法为最终变量 PI 指定值
System.out.println(Demo12.PI);
Son2 s=new Son2();
s.eat(); }

5:final关键字修饰形参

1:当形参被修饰为final,那么该形参所属的方法中不能被篡改。

2: 项目中主要用于一些只用来遍历未知数据的函数。将未知变量声明为final的。增强数据的安全性。

 class Demo14 {

     public static void main(String[] args) {

         System.out.println();
String[] arr = { "think in java", "java就业教程", "java核心技术" }; print(arr); } // 该方法,打印书名。
public static void print(final String[] arr) {
//arr = null; ,无法重新赋值 for (int x = 0; x < arr.length; x++) {
System.out.println(arr[x]);
}
} }

10:思考

为什么子类一定要访问父类的构造函数呢

1:子类继承了父类的属性,如果要使用父类的属性必须初始化,创建子类对象,必须先初始化父类属性

必须调用父类的构造方法。

2:为什么调用父类无参的构造函数

设计java语言之时,只知道编译器会默认添加无参的构造函数,有参的无法确定。

但是可以通过super关键字显式调用父类指定构造函数。

3:为什么super()this()语句要放在构造函数的第一行

子类可能会用到父类的属性,所以必须先初始化父类。

 

day6 面向对象(3)的更多相关文章

  1. (转)Python之路,Day6 - 面向对象学习

    本节内容:   面向对象编程介绍 为什么要用面向对象进行开发? 面向对象的特性:封装.继承.多态 类.方法.     引子 你现在是一家游戏公司的开发人员,现在需要你开发一款叫做<人狗大战> ...

  2. 转:Python之路,Day6 - 面向对象学习

    这篇文章写的不错,转来收了 转自:http://www.cnblogs.com/alex3714/articles/5188179.html   本节内容:   面向对象编程介绍 为什么要用面向对象进 ...

  3. 十一Python之路,Day6 - 面向对象学习

      本节内容:   面向对象编程介绍 为什么要用面向对象进行开发? 面向对象的特性:封装.继承.多态 类.方法.     引子 你现在是一家游戏公司的开发人员,现在需要你开发一款叫做<人狗大战& ...

  4. Python之路,Day6 - 面向对象学习

    本节内容:   面向对象编程介绍 为什么要用面向对象进行开发? 面向对象的特性:封装.继承.多态 类.方法. 引子 你现在是一家游戏公司的开发人员,现在需要你开发一款叫做<人狗大战>的游戏 ...

  5. day6 - 面向对象学习

    面向对象介绍 特性 class object 封装 继承 https://segmentfault.com/a/1190000002685939 python2 经典类是按照深度优先来继承的:新式类是 ...

  6. day6面向对象

    面向对象介绍(http://www.cnblogs.com/alex3714/articles/5188179.htm)     世界万物,皆可分类     世界万物,皆为对象     只要是对象,就 ...

  7. Python学习-day6 面向对象概念

    开始学习面向对象,可以说之前的学习和编程思路都是面向过程的,从上到下,一步一步走完. 如果说一个简单的需求,用面向过程实现起来相对容易,但是如果在日常生产,面向对象就可以发挥出他的优势了. 程序的可扩 ...

  8. Python3 day6面向对象

    http://www.cnblogs.com/alex3714/articles/5188179.html ====================生活中==================== 世界 ...

  9. python day6 面向对象

    把一个类变成具体的实例化的过程叫做类 实例化:把一个类变成一个具体对象的过程 __init__  构造函数,在实例化时初始化数据 __init__方法的第一个参数永远是self,表示创建的实例本身,因 ...

  10. day6面向对象--类的特殊成员方法

    类的特殊成员方法 1. __doc__ 表示类的描述信息 class Func(object): '''__doc__方法是用来打印类的描述信息''' def tell(self): pass def ...

随机推荐

  1. H2 database 操作操作内存表

    本例开发工具为 NetBeans,使用b2前提安装jdk. 第一步:在官网下载驱动包 :http://www.h2database.com ,本例版本为: h2-1.4.192.jar 第二步:安装开 ...

  2. RPM包的使用

    不同yum安装源配置文件 ls -l /etc/yum.repo.d RPM包的主包和子功能包 mount /dev/cdrom /media/cdrom cd /media/cdrom/Packag ...

  3. 关于String,StringBuffer与StringBuilder的区别

    String是字符串常量对象,对其进行改变时会相当影响效率,特别注意在循环中直接拼接字符串效率非常差. 如果你想改变字符串的值,更加推荐使用StringBuffer与StringBuilder两种可变 ...

  4. Coursera公开课Functional Programming Principles in Scala习题解答:Week 2

    引言 OK.时间非常快又过去了一周.第一周有五一假期所以感觉时间绰绰有余,这周中间没有假期仅仅能靠晚上加周末的时间来消化,事实上还是有点紧张呢! 后来发现每堂课的视频还有相应的课件(Slide).字幕 ...

  5. debug x86 汇编程序指南

    --------------------------------------------------------------------------------------------------- ...

  6. 基于欧氏距离和马氏距离的异常点检测—matlab实现

    前几天接的一个小项目,基于欧氏距离和马氏距离的异常点检测,已经交接完毕,现在把代码公开. 基于欧式距离的: load data1.txt %导入数据,行为样本,列为特征 X=data1; %赋值给X ...

  7. linux 防火墙配置与REJECT导致没有生效问题

    1.进入到/etc/sysconfig 如图 2.使用vi命令对iptables进行编辑."vi iptables",然后显示如图 # Firewall configuration ...

  8. 【转】数据存储——APP 缓存数据线程安全问题探讨

    http://blog.cnbang.net/tech/3262/ 问题 一般一个 iOS APP 做的事就是:请求数据->保存数据->展示数据,一般用 Sqlite 作为持久存储层,保存 ...

  9. webpack笔记1

    1.设置多个入口起点 多用于提取公共类库 a.利用commonChunkPlugin const webpack= require('webpack'); const path = require(' ...

  10. lk进kernel

    -- ] [upmu_is_chr_det] [] DRAM Rank : [] DRAM Rank[] Start = 0x40000000, Size = 0x25fc0000 [] DRAM R ...