Java学习笔记4

本文详细介绍了Java面向对象的四大特性:封装、继承、多态及构造过程。通过具体实例讲解了如何利用这些特性进行类的设计,并展示了如何通过多态实现不同子类间的差异屏蔽。
 
======================================================================
java
第四天
======================================================================
高内聚(independence: 一个对象独立[注意独立,不要其他对象的帮助]完成一个工作.
======================================================================
(1)
封装(encapsulation): 该隐藏的隐藏,该公开的公开.属性(property)[隐藏],方法[公开(有些公开,有些隐藏.)].//给自己用的方法私有,给别人用的方法公开. //公开声明,隐藏实现.[只修改实现这样对架构的影响最小.] 封装和弱藕合有关系
======================================================================
(2)
继承(inheritance):共性写在父类,个性(individual)写在子类. //单继承是java简单性的表现. java中的,父类的私有属性不继承到子类中.子类中.创建子对象要先创建一个父类,然后在加上一个子类对象[子类对象=父类对象+子类对象独特的地方].子类里边有父类和子类.子类能不能访问
单继承的好处: 类和类成为树状关系,不是网状结构.[java简单性的体现,但是能通过接口来实现多继承]
private: 不能继承.(但是子类里边有这个属性,如果修饰方法,子类就不能用了,属性的话,还能用一下.)
default: 同包子类能继承,不同包子类不能继承.
protected: 同包或者不同包的子类.
public: 任何类型:
protected: 的特殊使用方法如下:
package
b;
import a.*;
class TestProteced {
       publicstaticvoid main(String[] args) {
              B b = new B();
              b.m(); // 只有在子类的内部才能用父类的protected属性和方法.在即使是子类的对象外部使用也不行.
       }
}
class B extends A {
       void mm() {
              m(); // 在子类内部可以使用父类中protected 属性和方法.
       }
}
package a;
class A{
       void m(); // 外包中的方法.
}
(3)多态(polymorphism):方法覆盖: override //父子类才发生覆盖.方法名相同,参数表相同,返回值也要相同.修饰符可以不同[权限要越来越大[严->宽]] //1.4 中以上对
多态: 一个行为在不同的环境下有不同的行为方式.
多态分为:编译时多态[方法重载],和运行时多态.
//5.0: 不强制返回值一样(两个类必需)也可以返回类型的子类;
 
class Animanl{
       inta=10;
       protected A eat(){ // B A 的子类.
              System.out.println("hehe");
              returnnull;
       }
}
class Dog extends Animanl{
       int a=10; // 属性的遮盖.(shadow)
       super.a=1; // 要访问父类中的属性或者方法.super 关键字.
       super.eat(); // 调用父类的方法.
       protected B eat(){ // jdk 5.0 中返回值可以不同,有条件就是返回值可以是覆盖对象返回值的子类.
              System.out.println();
              returnnull;
       }
}
(3) 构造一个对象的过程:
一个对象的构造过程:
1.分配空间,
2.初始化属性
3.调用构造方法.
(4) 有父类的构造过程:有父类的类:
1. 递归的构造父类对象.//父类可能还有父类.
2. 分配本类的空间.
3. 初始化本类的属性.
4. 调用本类的构造方法.
//如果不想记那么多构造方法的语法,那么最好在每个类加上无参的构造方法.
有父类的类的构造方法例子:
---------------------------------------------
package test;
class Test{
       publicstaticvoid main(String[] args){
              int a=10;
              ClassB b=new ClassB(a); // 结果是: ClassA() ClassB(int )
       }     
}
class ClassA{
       public ClassA(){
              System.out.println("ClassA()");
       }
}
class ClassB{
       ClassB(int a){
              System.out.println("ClassA(int )");
       }
}
class ClassC{
       public ClassC(){
              System.out.println("ClassB()");
       }
}
class ClassD{
      // super(a); //如果
       ClassD(int a){
              System.out.println("ClassD(int a)");
       }
}
一个构造方法,如果不写,默认是super(), 既父类的无参构造方法.
class A{
       /*
       public A(){
              super();
       }
        */ 默认的产生[父类的无参构造方法].
}
===============================
package test;
 
class Super {
       //Super(){}
       public Super(int a) {
       }
}
 
class Sub extends Super {
       public Sub(int a) {
              super(a);
       } // 如果父类写了有参的构造方法,子类必需写一个有参的构造方法来构造父类。
}
如果在子类中有一个方法,这个方法方法名相同,参数表不同,叫作方法重载.
======================================================================
(5) 多态(polymorphism):Animal                    a=      new Dog();
编译时类型(引用类型)        运行时类型
主观(把它看成什么)            客观
3条原则:
 <1> 对象运行时类型不变.
 <2> 只能对一个引用调用其编译时类型定义的方法.  //对象只能调用父类中定义的方法.
 <3> 运行的时候,会根据运行时类型找,覆盖之后的方法. //
例子:
VCD,DVD机的例子:
遥控器()
package test;
publicclass TestPoly {
       publicstaticvoid main(String[] args) {
              Animal a = new Dog();
              a.eat();
              a.sleep();
              // a.call();
              Dog d;
              d = a; // 语法错误,不兼容类型.cannot convert        
              d = (Dog) a; // 要把a Dog.
              liucy l = new liucy(); // 不可以转换,不可能成功.
              Animal b = new Cat();
              Dog c;
              c = (Dog) b;// 编译时不出错,但是运行时会出异常: ClassCastException; 类型转换失败;
              //非要把b当狗看。
       }
}
class liucy {
}
class Dog extends Animal {
       void eat() {
       }
       void sleep() {
              System.out.println("狗睡觉!!");
       }
       void call() {
              System.out.println("狗叫!!wang wang ");
       }
}
class Cat extends Animal {
       void eat() {
       }
       void sleep() {
              System.out.println("猫睡觉!!");
       }
       void call() {
              System.out.println("猫叫!!miao ~~miao~~~~ ");
       }
}
(6) 判断两个类型是否相同.引用     instanceof();    类名
a            "是不是"       Dog
//判断引用的对象是否兼容. //用在强制类型转换之前.
System.out.println(a instanceof Dog); true;
System.out.println(a instanceof Cat); false;
System.out.println(a instanceof Animal); true;
强制类型转换: 当我们把父类的引用赋值给子类引用的时候,需要强制类型转换,
多态的作用: 屏蔽不同子类的差异.
======================================================================
作业:
1.设计一个形状类,方法:求周长和求面积
 形状类的子类:Rect(矩形),Circle(圆形)
 Rect类的子类:Square(正方形)
 不同的子类会有不同的计算周长和面积的方法
 创建三个不同的形状对象,放在Shape类型的数组里,分别打印出每个对象的周长和面积
总结:这个题目有写基础,没有代表性,也就不把代码写上去了,呵呵.
======================================================================
2.某公司的雇员分为以下若干类:
Employee:这是所有员工总的父类,属性:员工的姓名,员工的生日月份。方法:getSalary(int month) 根据参数月份来确定工资,如果该月员工过生日,则公司会额外奖励100元。
SalariedEmployee:Employee的子类,拿固定工资的员工。属性:月薪
HourlyEmployee:Employee的子类,按小时拿工资的员工,每月工作超出160小时的部分按照1.5倍工资发放。属性:每小时的工资、每月工作的小时数
SalesEmployee:Employee的子类,销售人员,工资由月销售额和提成率决定。属性:月销售额、提成率
BasePlusSalesEmployee:SalesEmployee的子类,有固定底薪的销售人员,工资由底薪加上销售提成部分。属性:底薪。
写一个程序,把若干各种类型的员工放在一个Employee数组里,写一个函数,打印出某月每个员工的工资数额。注意:要求把每个类都做成完全封装,不允许非私有化属性。
package test;
 
publicclass TestEmployee {
       publicstaticvoid main(String[] args) {
              Employee[] a = new Employee[4];
              a[0] = new SalariedEmployee("陈鹏烨", 12, 10000);
              a[1] = new HourlyEmployee("陈宗权", 10, 100, 300);
              a[2] = new SalesEmployee("小企鹅", 3, 100000, 0.05);
              a[3] = new BasePlusSalesEmployee("杨清", 10, 10000, 0.2, 5000);
              for (int i = 0; i < a.length; i++) {
                     System.out.println(a[i].getName() + "工资是: " + a[i].getSalary(10));
              }
       }
}
 
// 雇员类,是所有雇员的父类.把共性全部写在父类里边.
// 分析--->共性有: 姓名,生日 ;
class Employee {
       private String name;
 
       privateintbirthday;
 
       Employee() {
       }
 
       // 有参构造方法,用来构造父类.
       Employee(String name, int birthday) {
              this.name = name;
              this.birthday = birthday;
       }
 
       // 也是所有雇员的共性,每个雇员都会在生日的时候得到100元钱.
       double getSalary(int month) {
              if (month == birthday) {
                     return 100;
              }
              return 0;
       }
 
       // 用来获得雇员的姓名:
       String getName() {
              returnname;
       }
}
 
// 雇员类的子类,
class SalariedEmployee extends Employee {
       privateintmonthsalary; // 自己私有的属性,每个月的基本工资.
 
       SalariedEmployee() {
       } // 无参构造函数,记住最好写上.
       // 有参构造函数;
 
       SalariedEmployee(String name, int birthday, int monthsalary) {
              super(name, birthday); // 用来初始化,父类的的公有的属性.
              this.monthsalary = monthsalary;// 初始化子类的属性.
       }
 
       // 覆盖了父类的获得工资的方法.因为每类员工都有不同的工资方法.
       double getSalary(int month) {
              returnsuper.getSalary(month) + monthsalary; // 生日的钱+基本工资;
       }
}
 
// 雇员类的子类,小时工.
class HourlyEmployee extends Employee {
       // 自己私有的属性.每小时的工钱,和工作的小时数.
       privateinthoursalary;
 
       privateinthour;
 
       HourlyEmployee() {
       }
 
       // 有参构造函数,有来初始化自己私有的属性和父类中的属性.
       HourlyEmployee(String name, int birthday, int hoursalary, int hour) {
              super(name, birthday); // 初始化公有的属性.
              this.hoursalary = hoursalary; // 初始化私有的属性.
              this.hour = hour;
       }
 
       // 覆盖父类中获得工资的方法,
       double getSalary(int month) {
              double m = 0;
              if (hour >= 160) {
                     returnsuper.getSalary(month) + hoursalary * 160 + 1.5 * hoursalary
                                   * (hour - 160); // 生日的钱+小时*每小时的工资;
              } else
                     returnsuper.getSalary(month) + hoursalary * hour; // 生日的钱+小时*每小时的工资;
       }
}
 
// 雇员类的子类:
class SalesEmployee extends Employee {
       // 自己私有的属性: 销售额,提成率;
       privateintsale;
 
       privatedoublerate;
 
       SalesEmployee() {
       }
 
       // 有参构造函数,初始化类.
       SalesEmployee(String name, int birthday, int sale, double rate) {
              super(name, birthday); // 公有属性;
              this.sale = sale; // 私有属性;
              this.rate = rate;
       }
 
       // 覆盖了父类的获得工资的方法.
       double getSalary(int month) {
              returnsuper.getSalary(month) + sale * rate; // 生日的钱+提成;
       }
}
 
// SalesEmployee的子类,继承了SalesEmployee 的所有属性.
class BasePlusSalesEmployee extends SalesEmployee {
       // 本类私有的属性: 底薪. 其他全部继承子父类.
       privateintbasesalary;
 
       BasePlusSalesEmployee() {
       }
 
       BasePlusSalesEmployee(String name, int birthday, int sale, double rate,
                     int basesalary) {
              super(name, birthday, sale, rate); //初始化,和父类相同的属性
              this.basesalary = basesalary; //初始化自己的属性;
       }
 
       //覆盖了父类的获得薪水的方法.
       double getSalary(int month) {
              returnsuper.getSalary(month) + basesalary; //此时的getSalary() 已经计算过了生日的钱和提成的前,因此在这里只需要计算加上本类的独特属性底薪就可以了. //这就是继承的好处.
       }
}
总结: 这个题目要作出来很简单,要是做的符合面相对象的原则,就不那么简单了,首先,要把符合要求把所有类都作成完全私有的,这样子类就不能随便使用父类中的属性,虽然现在子类中有父类中的属性.如果要在子类在从新申请父类中有的属性,这样就浪费了空间,这样就会想到调用父类中能够操作父类属性的方法.很自然的就会想到父类中的构造方法.这样就用新的值初始化了父类中的属性,和子类中的属性,这样不会造成内存的浪费,而且会使代码简单易懂.也就是把共性放在父类中,把个性放在子类里边简单.
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

炼丹狮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值