======================================================================
java 第四天
======================================================================
高内聚( independence ) : 一个对象独立 [ 注意独立 , 不要其他对象的帮助 ] 完成一个工作 .
======================================================================
(1) 封装(encapsulation): 该隐藏的隐藏 , 该公开的公开 . 属性 (property)[ 隐藏 ], 方法 [ 公开 ( 有些公开 , 有些隐藏 .)].// 给自己用的方法私有 , 给别人用的方法公开 . // 公开声明 , 隐藏实现 .[ 只修改实现这样对架构的影响最小 .] 封装和弱藕合有关系
======================================================================
(2) 继承(inheritance): 共性写在父类 , 个性 (individual) 写在子类 . // 单继承是 java 简单性的表现 . java 中的 , 父类的私有属性不继承到子类中 . 子类中 . 创建子对象要先创建一个父类 , 然后在加上一个子类对象 [ 子类对象 = 父类对象 + 子类对象独特的地方 ]. 子类里边有父类和子类 . 子类能不能访问
单继承的好处 : 类和类成为树状关系 , 不是网状结构 .[java 简单性的体现,但是能通过接口来实现多继承 ] 。
private : 不能继承 .( 但是子类里边有这个属性 , 如果修饰方法 , 子类就不能用了 , 属性的话 , 还能用一下 .)
default
:
同包子类能继承
,
不同包子类不能继承
.
protected
:
同包或者不同包的子类
.
public
:
任何类型
:
protected:
的特殊使用方法如下:
package b;
package b;
import
a.*;
class
TestProteced {
public
static
void
main(String[] args) {
B b =
new
B();
b.m();
//
只有在子类的内部才能用父类的
protected
属性和方法
.
在即使是子类的对象外部使用也不行
.
}
}
class B extends A {
class B extends A {
void
mm() {
m();
//
在子类内部可以使用父类中
protected
属性和方法
.
}
}
package a;
package a;
class
A{
void
m();
//
外包中的方法
.
}
(3) 多态(polymorphism):方法覆盖: override //父子类才发生覆盖.方法名相同,参数表相同,返回值也要相同.修饰符可以不同[权限要越来越大[严->宽]] //1.4 中以上对
多态: 一个行为在不同的环境下有不同的行为方式.
多态分为:编译时多态[方法重载],和运行时多态.
//5.0: 不强制返回值一样(两个类必需)也可以返回类型的子类;
(3) 多态(polymorphism):方法覆盖: override //父子类才发生覆盖.方法名相同,参数表相同,返回值也要相同.修饰符可以不同[权限要越来越大[严->宽]] //1.4 中以上对
多态: 一个行为在不同的环境下有不同的行为方式.
多态分为:编译时多态[方法重载],和运行时多态.
//5.0: 不强制返回值一样(两个类必需)也可以返回类型的子类;
class
Animanl{
int
a
=10;
protected
A eat(){
// B
是
A
的子类
.
System.
out
.println(
"hehe"
);
return
null
;
}
}
class
Dog
extends
Animanl{
int
a=10;
//
属性的遮盖
.(shadow)
super
.a=1;
//
要访问父类中的属性或者方法
.
用
super
关键字
.
super
.eat();
//
调用父类的方法
.
protected
B eat(){
//
在
jdk 5.0
中返回值可以不同
,
有条件就是返回值可以是覆盖对象返回值的子类
.
System.
out
.println();
return
null
;
}
}
(3)
构造一个对象的过程:
一个对象的构造过程:
一个对象的构造过程:
1.分配空间,
2.初始化属性
3.调用构造方法.
(4) 有父类的构造过程:有父类的类:
2.初始化属性
3.调用构造方法.
(4) 有父类的构造过程:有父类的类:
1. 递归的构造父类对象.//父类可能还有父类.
2. 分配本类的空间.
3. 初始化本类的属性.
4. 调用本类的构造方法.
//如果不想记那么多构造方法的语法,那么最好在每个类加上无参的构造方法.
有父类的类的构造方法例子:
---------------------------------------------
package test;
2. 分配本类的空间.
3. 初始化本类的属性.
4. 调用本类的构造方法.
//如果不想记那么多构造方法的语法,那么最好在每个类加上无参的构造方法.
有父类的类的构造方法例子:
---------------------------------------------
package test;
class
Test{
public
static
void
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{
class A{
/*
public A(){
super();
}
*/
默认的产生
[
父类的无参构造方法
].
}
===============================
package test;
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;
======================================================================
(5) 多态(polymorphism):Animal a= new Dog();
编译时类型(引用类型) 运行时类型
主观(把它看成什么) 客观
3条原则:
<1> 对象运行时类型不变.
<2> 只能对一个引用调用其编译时类型定义的方法. //对象只能调用父类中定义的方法.
<3> 运行的时候,会根据运行时类型找,覆盖之后的方法. //
例子:
VCD,DVD机的例子:
遥控器()
package test;
public
class
TestPoly {
public
static
void
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;
(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;
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;
public
class
TestEmployee {
public
static
void
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
;
private
int
birthday
;
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() {
return
name
;
}
}
//
雇员类的子类
,
class
SalariedEmployee
extends
Employee {
private
int
monthsalary
;
//
自己私有的属性
,
每个月的基本工资
.
SalariedEmployee() {
}
//
无参构造函数
,
记住最好写上
.
//
有参构造函数
;
SalariedEmployee(String name,
int
birthday,
int
monthsalary) {
super
(name, birthday);
//
用来初始化
,
父类的的公有的属性
.
this
.
monthsalary
= monthsalary;
//
初始化子类的属性
.
}
//
覆盖了父类的获得工资的方法
.
因为每类员工都有不同的工资方法
.
double
getSalary(
int
month) {
return
super
.getSalary(month) +
monthsalary
;
//
生日的钱
+
基本工资
;
}
}
//
雇员类的子类
,
小时工
.
class
HourlyEmployee
extends
Employee {
//
自己私有的属性
.
每小时的工钱
,
和工作的小时数
.
private
int
hoursalary
;
private
int
hour
;
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) {
return
super
.getSalary(month) +
hoursalary
* 160 + 1.5 *
hoursalary
* (
hour
- 160);
//
生日的钱
+
小时
*
每小时的工资
;
}
else
return
super
.getSalary(month) +
hoursalary
*
hour
;
//
生日的钱
+
小时
*
每小时的工资
;
}
}
//
雇员类的子类
:
class
SalesEmployee
extends
Employee {
//
自己私有的属性
:
销售额
,
提成率
;
private
int
sale
;
private
double
rate
;
SalesEmployee() {
}
//
有参构造函数
,
初始化类
.
SalesEmployee(String name,
int
birthday,
int
sale,
double
rate) {
super
(name, birthday);
//
公有属性
;
this
.
sale
= sale;
//
私有属性
;
this
.
rate
= rate;
}
//
覆盖了父类的获得工资的方法
.
double
getSalary(
int
month) {
return
super
.getSalary(month) +
sale
*
rate
;
//
生日的钱
+
提成
;
}
}
// SalesEmployee
的子类
,
继承了
SalesEmployee
的所有属性
.
class
BasePlusSalesEmployee
extends
SalesEmployee {
//
本类私有的属性
:
底薪
.
其他全部继承子父类
.
private
int
basesalary
;
BasePlusSalesEmployee() {
}
BasePlusSalesEmployee(String name,
int
birthday,
int
sale,
double
rate,
int
basesalary) {
super
(name, birthday, sale, rate);
//
初始化
,
和父类相同的属性
this
.
basesalary
= basesalary;
//
初始化自己的属性
;
}
//
覆盖了父类的获得薪水的方法
.
double
getSalary(
int
month) {
return
super
.getSalary(month) +
basesalary
;
//
此时的
getSalary()
已经计算过了生日的钱和提成的前
,
因此在这里只需要计算加上本类的独特属性底薪就可以了
. //
这就是继承的好处
.
}
}
总结: 这个题目要作出来很简单,要是做的符合面相对象的原则,就不那么简单了,首先,要把符合要求把所有类都作成完全私有的,这样子类就不能随便使用父类中的属性,虽然现在子类中有父类中的属性.如果要在子类在从新申请父类中有的属性,这样就浪费了空间,这样就会想到调用父类中能够操作父类属性的方法.很自然的就会想到父类中的构造方法.这样就用新的值初始化了父类中的属性,和子类中的属性,这样不会造成内存的浪费,而且会使代码简单易懂.也就是把共性放在父类中,把个性放在子类里边简单.