文档库 最新最全的文档下载
当前位置:文档库 › 封装,接口,继承,覆盖,构造过程,多态用法

封装,接口,继承,覆盖,构造过程,多态用法

封装,接口,继承,覆盖,构造过程,多态用法
封装,接口,继承,覆盖,构造过程,多态用法

封装,接口,继承,覆盖,构造过程,多态用法

一、封装(encapsulation)

定义:封装就是将客户端不应看到的信息包裹起来。使内部执行对外部来看不一种不透明的、是一个黑箱,客户端不需要内部资源就能达到他的目的。

1.事物的内部实现细节隐藏起来

2.对外提供一致的公共的接口――间接访问隐藏数据

3.可维护*

--------------------------------------------------------------------------------

二、继承(inherit)

JAVA继承特点

继承:父类的成员能否继承到子类?

对类成员访问的**及子类继承情况:(从严到宽)

private 私有,本类内部不能继承

(default) 本类+同包同包子类可继承

protected 本类+同包+子类可以继承

public 公开任何地方都可以访问能继承到子类

--------------------------------------------------------------------------------

覆盖

1、定义:覆盖了一个方法并且对其重写,以求达到不同的作用。

2、用法:

a、最熟悉的覆盖就是对接口方法的实现

b、在继承中也可能会在子类覆盖父类中的方法

3、产生“覆盖”的条件:

1、方法名:相同

2、参数表:相同(个数,类型)

3、访问**符:相同或者更宽

4、返回值类型:相同或者子类返回的类型是父类返回的类型的子类

5、不能抛出比subclass(父类)更多的异常

注意:当我们在子类中创建的静态方法,它并不会覆盖父类中相同名字的静态方法。

class Parent

{

public void nonStaticMethod()

{

System.out.println("Parent's Non-Static Method is Called"); }

public static void staticMethod()

{

System.out.println("parent's static method is called");

}

}

class Child extends Parent

{

public void nonStaticMethod()

{

System.out.println("child's non-static method is called"); }

public static void staticMethod()

{

System.out.println("child's static method is called");

}

}

public class Test

{

public static void main(String args[])

{

Parent p1 = new Parent();

Parent p2 = new Child();

Child c = new Child();

System.out.print("Parent.static: "); Parent.staticMethod(); System.out.print("p1.static: "); p1.staticMethod(); System.out.print("p2.static: "); p2.staticMethod(); System.out.print("p1.nonStatic: "); p1.nonStaticMethod(); System.out.print("p2.nonStatic: "); p2.nonStaticMethod(); System.out.print("Child.static: "); Child.staticMethod(); System.out.print("c.static: "); c.staticMethod(); System.out.print("c.nonStatic: "); c.nonStaticMethod();

}

}

程序的运行结果为:

Parent.static: parent's static method is called

p1.static: parent's static method is called

p2.static: parent's static method is called

p1.nonStatic: Parent's Non-Static Method is Called

p2.nonStatic: child's non-static method is called

Child.static: child's static method is called

c.static: child's static method is called

c.nonStatic: child's non-static method is called

值得注意的是p2实际上是一个Child的类型的引用,然而在调用静态方法的时候,它执行的却是父类的静态方法,而不是Child的静态方法,而调用p2的非静态方法的时候执行的是Child的非静态方法,为什么呢?原因是静态方法是在编译的时候把静态方法和类的引用类型进行匹配,而不是在运行的时候和类引用进行匹配。因此我们得出结论:当我们在子类中创建的静态方法,它并不会覆盖父类中相同名字的静态方法。

--------------------------------------------------------------------------------

构造

(java编程思想定义为:构造器初始化)

对象的构造过程:

首先为对象分配内存空间,包括其所有父类的可见或不可见的变量的空间,并初始化这些变量为默认值,如int类型为0,boolean类型为false,对象类型为null。。。。

然后用下述5个步骤来初始化这个新对象:

1)分配参数给指定的构造方法;

2)如果这个指定的构造方法的第一个语句是用this指针显式地调用本类的其它构造方法,则递归执行这5个步骤;如果执行过程正常则跳到步骤5;

3)如果构造方法的第一个语句没有显式调用本类的其它构造方法,并且本类不是Object类(Object是所有其它类的祖先),则调用显式(用super指针)或隐式地指定的父类的构造方法,递归执行这5个步骤;如果执行过程正常则跳到步骤5;

4)按照变量在类内的定义顺序来初始化本类的变量,如果执行过程正常则跳到步骤5;

5)执行这个构造方法中余下的语句,如果执行过程正常则过程结束。

对分析本文的实例最重要的,用一句话说,就是“父类的构造方法调用发生在子类的变量初始化之前”。可以用下面的例子来证明:

列1

class Animal

{

Animal()

{

System.out.println("Animal");

}

}

class Cat extends Animal

{

Cat()

{

System.out.println("Cat");

}

}

class Store

{

Store()

{

System.out.println("Store");

}

}

public class Petstore extends Store

{

Cat cat = new Cat();

Petstore()

{

System.out.println("Petstore");

}

public static void main(String[] args)

{

new Petstore();

}

}

运行这段代*,它的执行结果如下:

Store

Animal

Cat

Petstore

从结果中可以看出,在创建一个Petstore类的实例时,首先调用了它的父类Store的构造方法;然后试图创建并初始化变量cat;在创建cat时,首先调用了Cat类的父类Animal的构造方法;其后才是Cat的构造方法主体,最后才是Petstore类的构造方法的主体。

列2

class Animal

{

Animal()

{

System.out.println("Animal");

}

}

class Cat extends Animal

{

Cat()

{

System.out.println("Cat");

}

}

class Cat2 extends Animal

{

Cat2()

{

System.out.println("Cat2");

}

}

class Store

{

Cat2 cat=new Cat2();

Store()

{

System.out.println("Store");

}

}

public class Petstore extends Store {

Cat cat = new Cat();

Petstore()

{

System.out.println("Petstore");

}

public static void main(String[] args) {

new Petstore();

}

}

运行这段代*,它的执行结果如下:Animal

Cat2

Store

Animal

Cat

Petstore

这例1和例2,使我更了解了类的构造过程:

类在new实例的时候

a。第一步构造类的成员变量

这里需要注意的:

a)即使变量定义散布于方法定义之间,它们仍旧会在任何方法(包括构造函数)被调用之前得到初始化

b)初始化的顺序是先“静态”对象(初始化过后,静态对象不会再被初始化),而后是“非静态”对象。

第二步调用构造方法。

b。如果有父类,那么就是先构造父类的成员变量,然后再调用父类的构造方法,然后再a。

--------------------------------------------------------------------------------

1.从本质上来说,包是将类组合在一起形成代*模块的一种机制,可以将包看成一个“文件夹”,而包里的各类,则是“文件”。

用途:避免命名冲突;可以在更广的范围保护类,数据和方法。

2.创建包

package a;//a是包名

3.导入包

1) import package a.* //a是包名。字符"*"则导入了包里的所有类和接口。

2) import package a.b //a是包名,b是类名。该*作导入了a包里的b类,而不会导入其它类。

4.使用其它包的类,而没有用import导入该包,*作如下:

a.b x=new a.b(); //a是包名,b是a包里的类,x是刚创建的该类的实例名。

怎样理解封装,继承,多态!三者的区别?

封装:每个对象都包括进行*作所需要的所有信息,而不依赖于其他对象来完成自己的*作。通过类的实例来实现。

好处:良好的封装可以降低耦合度;类的内部可以**修改;类具有对外的清晰接口。

继承:IS-A的关系。A is-a B:A是B,A可以继承B。A是B的一个特例,特殊化,A又可以具备自己独有的个*。三点:

子类拥有父类非private的属*和功能(父类的构造函数例外,可以用base关

键字访问,base代表着父类);

子类具有自己的属*和功能,即子类可以扩展父类没有的属*和功能;

子类可以以自己的方式重写父类的功能。

缺点:父类变,子类不得不变,父子是一种强耦合的关系。

多态:不同的对象可以执行相同的动作,但要通过他们自己的实现代*来执行。注意点:

子类以父类的身份出现;

子类在运行时以自己的方式实现;

子类以父类的身份出现时,子类特有的属*和方法不可以使用。

为了使子类的实例完全接替来自父类的类成员,父类必须将该成员声明为虚拟的(virtual),子类可以选择使用override将父类的实现替换为自己的实现,这就是多态。

1。类是对对象的一个抽象,同时类也为对象进行了封装。所谓封装是说类的设计者只是为使用者提供类对象可以访问的部分,而对于类中其他隐藏起来的成员变量方法,用户不能访问。

实现方式:A:在类的定义中设置对对象中成员变量和方法进行访问的权限; B:提供一个统一的供其他类引用的方法;

C:其它对象不能直接修改文本对象所拥有的属*和方法。

2。访问权限:

A:private的成员变量和方法只能被这个类本身的方法访问;

B:默认的成员变量和方法只被同一个包内的其它所有类都可访问,包外不可; C: protected的成员可以被这个类的本身、它的子类(同不同包均可)访问; D: public 完全公开。一个程序里最多只能有一个类被修饰为public,若程序中没有任何public 类,且文件名是程序中的一个类名,则该类被视做public 注:不能用protected和private饰!!!!

3。类的继承:

3.1 类继承的实现:

A:java中Object类是java中所有类的祖宗!(P209)

儿子A extends 老爸------只能有一个老爸!

3.2 this和super:

this: this.数据成员this.实例方法this(参数)--引用本类中其他构造方法。super:表示当前对象父类对象的引用

super.数据成员super.实例方法super(参数)--引用父类的构造方法。--通常在实现子类的构造方法时,要先调用父类的构造方法!并且用来调用父类构造方法的super()必须放在子类构造方法的句首

3.3 初始化顺序:

A 对象的初始化顺序:先静态成员,再非静态成员,再构造方法,

B 继承中构造方法的调用顺序:先父类,再子类。

3.4 对象之间的类型转换:

对象转换的圣经:只能说猫是哺*动物,不能说哺*动物是猫!!!当说猫是哺*

动物时,猫将失掉猫独有的属*和行为!!!(作为猫时新增的成员变量和方法)哺*动物aa=new 猫()---猫是哺*动物(要通过IS-A测试)

4.千呼万唤始出来------多态!

所谓多态就是同一方法获得不同的行为特*!

分为:

A 编译时多态*---重载(参数个数不同或参数类型不同)

B 动态多态*----覆盖(改写后的方法不能比覆盖的方法有更严格的访问权限--只能更加开放& 改写后的方法不能比被覆盖的法产生更多的例外)

****************************************************** ************

放点小音乐吧!

**** ******* 第一曲final:

1。final type 变量名=初值---常量

2。final 方法---该方法任何时候都不可以覆盖,但可以被重载。

3。final 类----该类不能被继承并覆盖其内容。(像System类,String类)第二曲native: 本地引用说明符^@^

java允许在程序中直接引用本地机上非java语言编写的程序。

native type programName([参数列表]);

programName是要引用的程序名,以方法的形式出现。由于是引用,具体执行的*作都包含在源程序中,所有programName后无具体方法体!

****************************************************** ************

一。深入继承:

1》设计继承树:

(1)找出具有共同属*和行为的对象(狼和狗与羊^^---动物共同的属*)

(2)设计代表共同状态与行为的类(都属于动物!---父类)

(3)决定子类是否需要让某项行为有特定不同运作的方式(都会吃,但羊只吃草---方法的覆盖)

(4)通过寻找使用共同行为的子类找出更多抽象化的机会(狼和狗属于犬科!!!--再继承)

(5)检查设计是否合理(IS-A)

(6)大功告成!

2》继承的意义:

(1)避免了重复的代*(子类会时时响应父类的改变)

(2)定义出共同的协议(服务于多态^^)

?当定主义出一组类的父型时,你可以用子型的任何类来填补任何需要或期待父型的位置?

二。深入多态:

(1) class Vet{

public void giveShot(Animal a){

a.makeNoise();

}

}

class PetOwner{

public void start(){

Vet v=new Vet();

Dog d=new Dog();

Hippo h=new Hippo();

v.giveShot(d);

V.giveSHot(h);

}

}

在此例中如果用Animal类型来声明它的参数(返回类型、数组的类型),则程序代*就可以处理所有Animal的子类。这意味着其它人只要注意到要扩充过Animal就可以利用你的Vet!(P168)

如果此例不用多态,那么每一种动物都要写出不同的方法--这是何等悲哀!!

(2)接口:

多态意味着“很多形式”,可以把儿子当作爸爸或爷爷!!

可以通过继承来定义相关类间的共同协议(方法就是协议的标志!),这样就等同于在对其他程序代*声明:“我所有的子类都能肠系用这些方法来执行这几项工作!”

为了避免出现“致命方块”所以java不允许出现多继承,接口正是我们的救星!java接口是100% 的纯抽象类。而且使用接口可以继承一个以上的来源,同时其他类也可以实现同一个接口中。所以可以为不同的需求组合出不同的继承层次!

三。如何判断应该是设计类、子类、抽象类或接口呢?

(1)如果新类无法对其他的类通过IS-A测试时,就设计不继承其他类的类。

(2)只有在需要某类的特殊化版本时,以覆盖或增加新的方法来继承现有的类。

(3)当你需要定义一群子类的模板,又不想让其他人初始化此模版时,设计出抽象的类给他们用。

(4)如果想要只定义出类可以扮演的角色,使用接口。

说那么多

自己经常用用就知道了~封装,继承,多态

封装就是把孩子放到一块管理

继承就是生孩子

多态男人,女人,人妖,就是人的多态

你认为大家不理解吗?这些东西,只有用了先知道。

多态,你写过名称相同,参数不同的函数吗?

继承,你的所有aspx页面,不都是继承Page吗?

封装,你没有自己写过类吗?你类里没有封装方法吗?

接口主要涉及跨平台、跨语言、移植*要求较高的编程

一般情况下不会用到的......

面向对象的三个特征.继承,封装和多态.

C#是一种现代的面向对象的语言.

继承(inheritance):继承是一个面向对象的词语.说明,一个类(派生类)能分享,其它类(基类)的特征和行为.派

生类和基类是"is a"的关系.

base classes(基类):通常基类可以自己实例化,或被继承.派生类继承基类中的成员,被标记为protected或更大

的权限.语法: class (derive class name):(base class name)

例子:

//基类

public class Contact

{

//默认私有的字段

string name;

string email;

string address;

//构造函数

public Contact()

{

// statements ...

}

//属*

public string Name

{

get

{

return name;

}

set

{

name = value;

}

}

public string Email

{

get

{

return email;

}

set

{

email = value;

}

}

public string Address

{

get

{

return address;

}

set

{

address = value;

}

}

}

//派生类

public class Customer : Contact

{

//自己的私有字段

string gender;

decimal income;

public Customer()

{

// statements ...

}

}

在上面的例子中,Customer 是

Contact的子类,不但,继承了父类的成员,name,email,address;还有自己的成员,gender,income.

abstract classes(抽象类):抽象类是一种特殊的基类.除过普通的类成员,它们还有抽象的类成员.抽象类成员,

是不能被实例化的方法和属*.所有直接从抽象类派生的类,必须实现抽象的方法和属*.抽象类不能被实例化.

例子:

//抽象类

abstract public class Contact

{

protected string name;

public Contact()

{

// statements...

}

//抽象方法

public abstract void generateReport(); //抽象属*

abstract public string Name

{

get;

set;

}}

public class Customer : Contact

{

string gender;

decimal income;

int numberOfVisits;

public Customer()

{

// statements

}

public override void generateReport() {

// unique report

}

public override string Name

{

get

{

numberOfVisits++;

return name;

}

set

{

name = value;

numberOfVisits = 0;

}

}

}

public class SiteOwner : Contact

{

int siteHits;

string mySite;

public SiteOwner()

{

// statements...

}

public override void generateReport()

{

// unique report

}

public override string Name

{

get

{

siteHits++;

return name;

}

set

{

name = value;

siteHits = 0;

}

}

}

上面的例子,定义了三个类.一个抽象类,两个派生类.实现了父类的方法和属*."override"修饰符,实现了抽象

类的方法.

Calling Base Class Members(调用基类成员)

派生类能调用基类成员,如果,成员的修饰符是"protected"或更大权限.在适当的上下文条件下,好像调用自己的

成员一样.

例子:

abstract public class Contact

{

private string address;

private string city;

private string state;

private string zip;

public string FullAddress()

{

string fullAddress =

address + '\n' +

city + ',' + state + ' ' + zip;

return fullAddress;

}

}

public class Customer : Contact

{

public string GenerateReport()

{

string fullAddress = FullAddress();

// do some other stuff...

return fullAddress;

}

}

上面的例子中,派生类调用基类的方法:FullAddress();

基类的构造函数,可以被派生类调用,用base().

例子:

abstract public class Contact

{

private string address;

public Contact(string address)

{

this.address = address;

}

}

public class Customer : Contact

{

public Customer(string address) : base(address)

{

}

}

例子中,派生类没有address成员,可以调用基类的构造函数. Hiding Base Class Members(隐藏基类成员)

派生类可以和基类有同样名字的成员.这时,就会隐藏基类的成员. 例子:

abstract public class Contact

{

private string address;

private string city;

private string state;

private string zip;

public string FullAddress()

{

string fullAddress =

address + '\n' +

city + ',' + state + ' ' + zip;

return fullAddress;

}

}

public class SiteOwner : Contact

{

public string FullAddress()

{

string fullAddress;

// create an address...

return fullAddress;

}

}

在例子中,派生类和基类有同样的成员,FullAddress(),当调用时,基类的方法会被隐藏.

尽管基类的成员被隐藏,仍然可以访问基类的成员,通过,base关键字,调用基类的引用.

例子中,密封类不能被继承.

你用不到接口,说了也没有用。

petshop就用到了接口,数据工厂,具体不不是很理解。

接口只定义方法,不实现。数据工厂的原理似乎是根据接口调用。

你就可以不考虑接口是怎么实现的。

比如你dal定义的统一的接口,这个接口可以用*作access的类实现。

也可以用*作ms sql的类实现。你改变了*作类,但是你调用的时候是用接口。所以不用改代*,这一块代*。

封装:比如你只需要指定他是一个人,能干什么就行,而不需要知道他是怎么去干的。你只能通过命令让他去干事情,而不是你拉着他的手一步一步教他去怎么做。

继承:比如你老爸是个人,你是你老爸的儿子,那么你也是一个人,你老爸有的东西你都有,但是你有不同于你老爸,你除了拥有你老爸的东西外还多出了自己东西。

多态:比如一个人,他拥有手,但是如果你让他举起一只手,他可能举起左手,也可能举起右手,但是如果你让他举起左手,那他就能唯一确定的举起左手。

这其实是典型的滥用继承的一个现象。如今所有结构化编程人员都用OOPL了,所以OOPL编程要谨慎对待那种滥用OO的情况,用过了比不会用更危险,因为它发现和矫正起来更难。

OO设计中,如果B类继承自A类,就是说B类对象“is_a”A类,例如猪是动物,房子是建筑物,白马是马。同一个对象有不同的身份(接口),因此我们可以有两种不同的分类,但是并不改变“同一个对象”的基本概念,xyz住院病人是xyz病人,是同一个病人,而不是两个病人。如果你说儿子继承老爸,就等于说儿子和老爸是同一个人,这就诡异和胡乱使用了继承概念。生活中的遗产继承如果你“按名词”对号入座为OO设计中的继承,就会出现设计上的严重错误。所以最怕有些人不问名词的内涵,仅凭名词相似就附会概念的情况。

不要以为只有不懂OO的人会犯这个错误,我看过并且我在csdn上推荐过一本关于.net架构设计的入门书,中国人写的,虽然它的具体内容显得清晰易懂很好,但是我也说过那本书上在前头讲继承和组合的架构概念是竟然用2、3页篇幅以“富爸爸、穷爸爸”留遗产的例子来比喻继承技术,其实是很荒唐的。虽然那本书我推荐作为架构入门书看看,因为其后边的实际具体内容还是很好的,但是前边一章理论方面的基本概念的问题也确实有误导*。

编写代*的语法是不应该滥用的,你要首先想到用代*来表达你的设计思想,而不是用代*来败坏你本来清晰的设计思想。所以,设计思想,可以给完全不懂编程的人使用,才是真正的设计思想。如果你为了编程方便,根据“名词匹配”哪种方式去附会地学习,早晚会像邯郸学步一样可痛苦地不得不设计转型。研究软件设计,请忘记你的编程语言,忘记的计算机技术,认真研究语言、逻辑,在一张白纸上你可以画出设计模型,并且可以将给所有编程的外行听你的设计模型。封装:每个对象都包括进行*作所需要的所有信息,而不依赖于其他对象来完成自己的*作。通过类的实例来实现。

好处:良好的封装可以降低耦合度;类的内部可以**修改;类具有对外的清晰接口。

继承:IS-A的关系。A is-a B:A是B,A可以继承B。A是B的一个特例,特殊化,A又可以具备自己独有的个*。三点:

子类拥有父类非private的属*和功能(父类的构造函数例外,可以用base关键字访问,base代表着父类);

子类具有自己的属*和功能,即子类可以扩展父类没有的属*和功能;

子类可以以自己的方式重写父类的功能。

缺点:父类变,子类不得不变,父子是一种强耦合的关系。

多态:不同的对象可以执行相同的动作,但要通过他们自己的实现代*来执行。注意点:

子类以父类的身份出现;

子类在运行时以自己的方式实现;

子类以父类的身份出现时,子类特有的属*和方法不可以使用。

为了使子类的实例完全接替来自父类的类成员,父类必须将该成员声明为虚拟的(virtual),子类可以选择使用override将父类的实现替换为自己的实现,这就是多态。

这其实也是一种很过时的说法。随着进15年OO的流行,过去大书特书“优先使用基于对象的组合,而不是类的继承来实现复用”那些人都掉头来写如何用继承来实现复用了。例如微软在推广COM+体系的时代,几乎所有专为微软推广编程开发语言的编程书都这么说。但是它自己发布了.net战略,大家可以看看.net framework中的实现,例如https://www.wendangku.net/doc/fb11722972.html,控件或者winForm控件体系,不正是使用到了继承了吗?从一个根本不直接支持继承的COM体系过度到支持单继承的.net体系,写微软的编程书的作者于是就改口了。道理很简单,这句话没有一个可*作的原则*,什么叫做“优先”,当被自己证明是可以改变的时候,他就失去了可信*。

所以我说,“但是他们大多也没有从OO设计而纯粹是从编程角度去写的”、“编写代*的语法是不应该滥用的,你要首先想到用代*来表达你的设计思想”。

我们应该首先掌握OOAD设计思想,而不是纠缠于某一种编程语言,更不是纠缠于编程时是否方便。如果你因为编程时发现某些方法的名称恰好类似,甚至代*恰好类似,为了编程方便你把不同的类制造了一个继承关系,这跟设计能否保持一致就值得深深地怀疑和检验。我们设计软件,从分析、设计、编*、测试的逻辑和风格要保持一致,不能分析设计时很明白,一写代*就变了。“你要首先想到用代*来表达你的设计思想,而不是用代*来败坏你本来清晰的设计思想”。如果觉得这比较玄,那么你就忘记编程语言,假设自己是一个完全不懂编程的人首先来进行逻辑设计,然后你一定要设置检测程序来从系统外部发现实现时那种因为滥用继承、多态等来败坏程序设计逻辑一致*的现象,这样你的产品才能用的更长、更新改造过程来的更顺利。

封装:package 就等于打个包,包里面的东西是秘密,但是这个包有特定的用途,但是只能用名称来调用使用.

继承:inherit 就是copy,儿子copy了他老爸的基因,所以儿子有他老爸的所有的东西,包括老爸的钱就是自己的钱

(但老爸的老婆,可不是自己的老婆了,老婆就叫做构造函数)是不能继续的);

多态:multiState 比如说你去澡堂里洗澡,在池溏里,你一不小心往里面撒了泡尿,其它人做出什么样的反应呢?

有人打你,有的人骂你,有的人用眼睛瞪你,有的人... 根据你做出的这一件事情,而其它对象有不同的反应,这就是多态.

我并不赞同这种说法,软件设计的思想从初始的瀑布模型到增量迭代,再到现在热门敏捷开发,其实是一步一个脚印走过来的,或许一些概念已经变更,但某些思想仍然在继续传承。就像现在C#、Java满天飞,但是对于基本的数据结构和算法,像语言表面那么热闹吗?你用C# 实现一个冒泡排序,和用 C 甚至是Javascript 实现在本质上有很大的区别吗?抛开这些繁华的表面,我们是否有引以为根的东西,我觉得这才是重要的。

我入行的时间不是太长,做到现在快满一年了,外面漂泊了许久,因为种种原因,最后*起了程序员这个职业,抽以在语言特*方面的理解上有些浅薄(呵,除

对 .net 框架算是稍有了解之外,对于COM 什么的纯粹是两眼一抹黑)。但是,我相信,即使在程序设计这个日新月异的行业内,仍然有些东西在很长时间内是不会改变的,而这些是程序设计所共通的,每种语言都不可能绕过的东西。

所以,我不认为一个很重要并且目前仍然很有用的原则会因为时间的流逝而打上过时的标签,从商业的手段来推导技术上的原则,是否有些不恰当呢?况且微软不是全部,更何况微软的控件体系中对对象组合的应用,远多于继承的方式,可以查阅一下MSDN,几乎每个控件类的下面都有一长串所实现接口的列表,这些接口是用来做什么的呢?

其实我一直有个想法,就是对于需求的变更,尽量做到不更改原有的代*,而是通过增加新的代*,以一种插件的形式添加到原有系统中,这要怎么才能做到呢?必须设计良好的接口,那么就可以动态的用具有新功能的对象替换掉原有的功能模块对象,从而实现系统功能的变更,这其实也是基于一个典型的对象组合的应用。

类与接口在OO 设计中是不同的概念,这在很多年前就已经是定论了,虽然它们具有类似的表述形式,在一些语言中,还是用抽象类的概念去描述接口。但是,我认为,类侧重的是代*,描述的是它如何实现这个功能,而接口,则侧重于表述一个对象应该实现什么样的功能,而并不关心如何实现,这正是对象能够组合的基础。如果都仅只是类型,.NET 还有Java 为何要把接口单独定义出来,说接口是类型,那仅只是从编程的角度来理解,而不是OO 的角度。

实验04 类的继承与多态

实验四类的继承与多态 一、实验目的 1.掌握构造方法和成员方法重载的应用。 2.理解类的继承性的作用 3.领会面向对象编程的多态性。 二、实验内容与要求 基本概念 1.进一步理解继承的含义 新类可从现有的类中产生,并保留现有类的成员变量和方法并可根据需要对它们加以修改。新类还可添加新的变量和方法。这种现象就称为类的继承。 当建立一个新类时,不必写出全部成员变量和成员方法。只要简单地声明这个类是从一个已定义的类继承下来的,就可以引用被继承类的全部成员。被继承的类称为父类或超类(superclass),这个新类称为子类。 Java 提供了一个庞大的类库让开发人员继承和使用。设计这些类是出于公用的目的,因此,很少 有某个类恰恰满足你的需要。你必须设计自己的能处理实际问题的类,如果你设计的这个类仅仅实现了继承,则和父类毫无两样。所以,通常要对子类进行扩展,即添加新的属性和方法。这使得子类要比父类大,但更具特殊性,代表着一组更具体的对象。继承的意义就在于此。 2.了解成员变量的隐藏方式 所谓隐藏是指子类重新定义了父类中的同名变量,在子类L ine 中重新定义了x为x1,y 为y1,隐藏了父类Point 中的两个成员变量x 和y。子类执行自己的方法时,操作的是子类的变量,子类执行父类的方法时,操作的是父类的变量。在子类中要特别注意成员变量的命名,防止无意中隐藏了父类的关键成员变量,这有可能给程序带来麻烦。 3.了解成员方法的覆盖方式 (1)方法覆盖的定义与作用通过继承子类可以继承父类中所有可以被子类访问的成员方法,但如果子类的方法与父类方法同名,则不能继承,此时称子类的方法覆盖了父类的方法,简称为方法覆盖(override)。方法覆盖为子类提供了修改父类成员方法的能力。 4.理解类的多态性类的继承发生在多个类之间,而类的多态只发生在同一个类上。在一个类中,可以定义多个同名的方法,只要确定它们的参数个数和类型不同。这种现象称为类的多态。多态使程序简洁,为程序员带来很大便利。在O OP 中,当程序要实现多个相近的功能时,就给相应的方法起一个共同的名字,用不同的参数代表不同的功能。这样,在使用方法时不论传递什么参数,只要能被程序识别就可以得到确定的结果。 类的多态性体现在方法的重载(overload)上,包括成员方法和构造方法的重载。 实践应用

JAVA继承和多态实验报告

实验项目名称:继承和多态 (所属课程:Java语言程序设计) 院系:专业班级:姓名: 学号:实验地点:指导老师: 本实验项目成绩:教师签字:日期: 1.实验目的 (1)掌握类的继承机制。 (2)熟悉类中成员变量和方法的访问控制。 (3)熟悉方法或构造方法多态性。 2.实验内容 (1)模拟编写程序,理解类的继承、多态、继承和多态规则。 (2)独立编程,实现类的继承和多态。 3.实验作业 设计一个类Shape(图形)包含求面积和周长的area()方法和perimeter()方法以及设置颜色的方法SetColor(),并利用Java多态技术设计其子类Circle(圆形)类、Rectangle (矩形)类和Triangle(三角形)类,并分别实现相应的求面积和求周长的方法。每个类都要覆盖toString方法。 海伦公式:三角形的面积等于s(s-a)(s-b)(s-c)的开方,其中s=(a+b+c)/2 程序代码为: Class包 package Class; public class Shape { private String color = "while"; public Shape(String color){ this.color = color; } public void setColor(String color){ this.color = color; } public String getColor(){ return color;

} public double getArea(){ return 0; } public double getPerimeter(){ return 0; } public String toString(){ return"color:" + color; } } package Class; public class Circle extends Shape { private double radius; public Circle(String color,double radius) { super(color); this.radius = radius; } public void setRadius(double radius){ this.radius = radius; } public double getRadius(){ return radius; } public double getCircleArea(){ return 3.14*radius*radius; } public double getCirclePerimeter(){ return 3.14*2*radius; } public String toString(){

JAVA面向对象基础测试题,继承,封装,多态等测试题

JAVA面向对象基础测试题 提示:本题为第一阶段,JAVA面向对象基础部分练习题,包括对象,类,继承,封装,多态,接口,内部类等等,java核心基础,适合初学者对面向对象基础的知识进行测试,以便查漏补缺。 1. 程序执行的结果是:()。 01 public class Point{ 02 int y = 7; 03 public void step(int y) { 04 y += y; 05 System.out.println(y); 06 } 07 public static void main(String[] args) { 08

Point p = new Point(); 09 p.step(10); 10 } 11 } A.14 B.20 C.10 D.17 正确答案:B解析: 2. 程序的执行结果是:()。 01 public class Question { 02 private int num; 03 public static void main(String [] args){ 04 Question q = new Question();

05 q.num=13; 06 update(q); 07 System.out.println(q.num); 08 } 09 public static void update(Question q){ 10 q.num=9; 11 } 12 } A.13 B.9 C.0 D.4 正确答案:B解析: 3.

程序执行的结果是:()。 01 public class Answer { 02 public static void main(String[] args) { 03 int score = 20; 04 Answer ans= new Answer(); 05 ans.add(score); 06 System.out.println(" main:score = " + score); 07 } 08 void add(int score) { 09 System.out.println(" add:score=" + score++); 10 } 11

继承与多态习题

继承与多态习题 一.基本概念与基础知识自测题 8.1填空题 8.1.1 如果类α继承了类β,则类α称为(1)类,而类β称为(2)类。(3)类 的对象可作为(4)类的对象处理,反过来不行,因为(5)。如果强制转换则要注意(6)。 答案:(1)基类 (2)派生类 (3)派生类 (4)基类 (5)派生类有一些新成员 (6)只能派生类强制转换为基类 8.1.2 当用public继承从基类派生一个类时,基类的public成员成为派生类的(1)成员, protected成员成为派生类的(2)成员,对private成员是(3)。公有派生可以使其类的(4),所以公有派生是主流。 答案:(1)public成员 (2)protected成员 (3)不可访问 (4)接口不变 8.1.3 利用继承能够实现(1)。这种实现缩短了程序开发的时间,VC++中的(2)很 好地体现了这一点。 答案:(1)代码的复用 (2)MFC编程 8.1.4 一个派生类只有一个直接基类的情况称为(1),而有多个直接基类的情况称为 (2)。继承体现了类的(3)概念,这在MFC中得到了很好表现,MFC中只采用了(4)。 答案:(1)单继承 (2)多重继承 (3)层次 (4)单继承 8.1.5 C++中多态性包括两种多态性:(1)和(2)。前者是通过(3)实现的, 而后者是通过(4)和(5)来实现的。 答案:(1)编译时的 (2)运行时的 (3)函数和运算符的重载 (4)类继承关系 (5)虚函数 8.1.6 在基类中将一个成员函数说明成虚函数后,在其派生类中只要(1)、(2)和

(3)完全一样就认为是虚函数,而不必再加关键字(4)。如有任何不同,则认为是(5)而不是虚函数。除了非成员函数不能作为虚函数外,(6)、(7)和(8)也不能作为虚函数。 答案:(1)同虚函数名 (2)同参数表 (3)同返回类型。如基类中返回基类指针,而派生类中返回派生类指针是允许的 (4)virtual (5)重载 (6)静态成员函数 (7)内联函数 (8)构造函数 8.1.7 纯虚函数定义时在函数参数表后加(1),它表明程序员对函数(2),其本质 是将指向函数体的指针定为(3)。 答案:(1)=0 (2)不定义 (3)NULL 8.2简答题 8.2.1构造函数和析构函数可以继承吗?派生类构造函数各部分的执行次序是怎样的?答:构造函数和析构函数不可以继承。派生类构造函数各部分的执行次序是: 1.调用基类构造函数,按它们在派生类声明的先后顺序,依次调用。 2.调用新增成员对象的构造函数,按它们在类定义中声明的先后顺序,依次调用。 3.派生类的构造函数体中的操作。 8.2.2什么叫派生类的同名覆盖(override)? 答:如果派生类声明了一个和某个基类成员同名的新成员(当然如是成员函数,参数表也必须一样,否则是重载),派生类中的新成员就屏蔽了基类同名成员,类似函数中的局部变量屏蔽全局变量。称为同名覆盖(override)。 8.2.3派生类的析构函数中需完成什么任务?是否要编写对基数和成员对象的析构函数的 调用?为什么? 答:析构函数的功能是作善后工作,析构函数无返回类型也没有参数,情况比较简单。派生类析构函数定义格式与非派生类无任何差异,不要编写对基数和成员对象的析构函数的调用,只要在函数体内把派生类新增一般成员处理好就可以了,因为对新增的成员对象和基类的善后工作,系统会自己调用成员对象和基类的析构函数来完成。 8.2.4为什么要使用虚基类?怎样定义虚基类?用一个实例来解释虚基类在其派生类中的 存储方式。 答:在多重继承是有可能出现同一基类的两个拷贝,为避免这种情况,可使用虚基类。虚基类(virtual base class)定义方式如下: class派生类名:virtual 访问限定符基类类名{...}; class派生类名:访问限定符virtual基类类名{...}; virtual 关键字只对紧随其后的基类名起作用。

如何体现封装、继承、多态 编程人员看看

如何体现封装、继承、 编程人员看看! 如何体现封装、继承、多态 编程人员看看!! ! 什么事封装? 1. 保护数据成员, 不让类以外的程序直接访问或 修改,只能通过提供的公共的接口访问==>数据封 装。 2. 方法的细节对用户是隐藏的,只要接口不变, 内容的修改不会影响到外部的调用者==>方法封装。 3. 当对象含有完整的属性和与之对应的方法时称为 封装。 4. 从对象外面不能直接访问对象的属性, 只能通 过和该属性对应的方法访问。 5. 对象的方法可以接收对象外面的消息。 比如: Class A { private int prop; puplic int getProp() { return prop; }

public void setProp(int prop) { this.prop = prop; } } 属性 prop 是 private 的,外界不能直接访问, 但是外界可以通过调用 getProp()和 setProp()的方 法, 给对象发消息,从而完成某种功能。 什么事多态? 多态性的概念经常被说成事“一个接口,多种方 法”。这意味着可以为一组相关的动作作设计一个通 用 的接口。多态允许同一个接口被必于同一个类的多个 动作使用,这样就降低了程序的复杂性。再拿狗作比 喻, 一条狗的嗅觉是多态的。如果狗闻到猫的气味,它会 在吠叫并且追着它跑。如果狗闻到食物的气味,它将 分 泌唾液并向盛着食物的碗跑去。两种状况下同一种嗅 觉器官在工作,差别在于问到了什么气味,也就是有

两 种不同类型的数据作用于狗的鼻子!在 java 中,同一 个类中的 2 个或 2 个以上的方法可以有同一个名字, 只要 参数声明不同即可。在这种情况下,该方法就被称为 重载(Overload),这个过程称为方法重载(Method overloading)。方法重载是 java 实现多态的一种方 式。 有两种方式可以实现多态:* 1. 继承(子类继承父类(包括 abstract class,interf ace ect)) 2. 重载(同一个类中) 如果是面向对象程序设计的话,面向对象程序设 计中的另外一个重要概念是多态性。在运行时,通过 指向 基类的指针,来调用实现派生类中的方法。可以把一 组对象放到一个数组中,然后调用它们的方法,在这 种场 合下,多态性作用就体现出来了,这些对象不必是相 同类型的对象。当然它们都继承自某个类,你可以把 这些 派生类都放到一个数组中。如果这些对象都有同名方

C 的封装性、继承性和多态性概念

C++的封装性、继承性和多态性概念 封装的目的是增强安全性和简化编程,使用者不必了解具体的实现细节,而只是要通过外部接口,一特定的访问权限来使用类的成员。例如,在抽象的基础上,我们可以将时钟的数据和功能封装起来,构成一个时钟类。按c++的语法,时钟类的声明如下:class Clock { public: //共有成员,外部借口void SetTime(int NewH,int NewM,int NewS); void ShowTime(); private: //私有成员,外部无法访问int Hour,Minute,Second; } 可以看到通过封装使一部分成员充当类与外部的接口,而将其他的成员隐蔽起来,这样就达到了对成员访问权限的合理控制,使不同类之间的相互影响减少到最低限度,进而增强数据的安全性和简化程序的编写工作。什么是多态(Polymorphisn)?按字面的意思就是“多种形状”。引用Charlie Calverts对多态的描述——多态性是允许你将父对象设置成为和一个或更多的他的子对象相等 的技术,赋值之后,>>>父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作<<<(摘自“Delphi4 编程技术内幕”)。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。多态性在Object Pascal和C++中都是通过虚函数(Virtual Function)实现的。好,接着是“虚函数”(或者是“虚方法”)。虚函数就是允许被其子类重新定

义的成员函数。而子类重新定义父类虚函数的做法,称为“覆盖”(override),或者称为“重写”。“继承”是面向对象软件技术当中的一个概念。如果一个类A继承自另一个类B,就把这个A称为"B的子类",而把B称为"A的父类"。继承可以使得子类具有父类的各种属性和方法,而不需要再次编写相同的代码。在令子类继承父类的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类的原有属性和方法,使其获得与父类不同的功能。 ... 继承是指一个对象直接使用另一对象的属性和方法。事实上,我们遇到的很多实体都有继承的含义。例如,若把汽车看成一个实体,它可以分成多个子实体,如:卡车、公共汽车等。这些子实体都具有汽车的特性,因此,汽车是它们的"父亲",而这些子实体则是汽车的"孩子"。19. 多态的作用?主要是两个:1. 隐藏实现细节,使得代码能够模块化;扩展代码模块,实现代码重用; 2. 接口重用:为了类在继承和派生的时候,保证使用家族中任一类的实例的某一属性时的正确调用。

第七章继承多态练习题

第七章继承多态 一、选择题: 1、分析: class A { A() { } } class B extends A { //系统自动生成的构造方法和类的访问权限一样 } 哪两种说法是正确的? ( ) A:类B的构造方法是public的. B:类B的构造方法包含对this()的调用. C:类B的构造方法没有参数. D:类B的构造方法包含对super()的调用. 2、运行结果是:() class Base { Base() { System.out.print("Base"); } } public class Alpha extends Base { public static void main( String[] args ) { new Alpha(); new Base(); } } A: Base B: BaseBase C: 编译失败. D: 没有输出. E: 运行时异常. 3. 程序的运行结果是?() A: 编译失败. B: hello from a C: hello from b D: hello from b E: hello from a hello from a hello from b

4. 运行结果是:() class TestSuper { TestSuper(int i) { } } class TestSub extends TestSuper{ } class TestAll { public static void main (String [] args) { new TestSub(); } } A: 编译失败. B: 程序运行没有异常. C: 第7行抛出异常. D: 第2行抛出异常. 5. 程序的运行结果是?() A: 0 B: 1 C: 2 D: 编译失败. 6. 对于语句"B is a D" 和"B has a C",一下哪两种说法是正确的? ( ) A:D是B. B:B是D. C:D是C. D:B是C. E:D继承B. F:B 继承D. 7. 运行结果是?()

Java继承与多态实验报告

西安邮电大学 (计算机学院) 课内实验报告 实验名称:继承与多态 专业名称:计算机科学与技术 班级:计科1405班 学生姓名:高宏伟 学号:04141152 指导教师:刘霞林 实验日期:2016.10.13

一、实验目的 通过编程和上机实验理解Java 语言的继承和多态特性,掌握变量的隐藏、方法的覆盖、重载,掌握抽象类和接口的使用。 二、实验要求 1.编写体现类的继承性(成员变量、成员方法、成员变量隐藏)的程序。 2.编写体现类的多态性(成员方法重载)的程序。 3.编写体现类的多态性(构造方法重载)的程序。 4.编写使用接口的程序。 三、实验内容 (一)类的继承 1.创建公共类Student. (1)编写程序文件Student.java,源代码如下: public class Student { protected String name; //具有保护修饰符的成员变量 protected int number; void setData(String m,int h) //设置数据的方法 { name =m; number= h; } public void print() //输出数据的方法 { System.out.println(name+", "+number); } } (2)编译Student.java,产生类文件Student.class。 2.创建继承的类Undergraduate

(1)程序功能:通过Student 类产生子类undergraduate,其不仅具有父类的成员变量name()、number(学号),还定义了新成员变量academy(学院)、department (系)。在程序中调用父类的print 方法。 (2)编写Undergraduate 程序: class Undergraduate extends Student { 【代码1】//定义成员变量academy 【代码2】//定义成员变量department public static void main(String args[]) { 【代码3】//创建一个学生对象s 【代码4】//用父类的setData方法初始化对象s 【代码5】//对象s调用print方法 【代码6】//创建一个大学生对象u 【代码7】//调用父类的成员方法setData初始化对象u 【代码8】//设置对象u的成员变量academy 【代码9】//设置对象u的成员变量department System.out.print(https://www.wendangku.net/doc/fb11722972.html,+", "+u.number+", "+u.academy+", "+u.department); } } (3)编译并运行程序 注意:公共类Student 与undergraduate 类要在同一文件夹(路径)。 (二)方法的重载 (1)程序功能:对不同的数进行排序输出。在IntSort 类中定义3 个同名的方法sort。 (2)编写Sort.java 文件,源代码如下。 import java.awt.Graphics; import java.applet.Applet; class IntSort { public String sort(int a, int b) { if (a>b) return a+""+b; else return b+""+a; } public String sort(int a, int b, int c) { int swap; if (a

面向对象的三大特性(封装-继承-多态)

一丶封装 1 权限修饰符 可以用来修饰成员变量和成员方法,对于类的权限修饰只可以用public和缺省default。 被public修饰的类可以在任意地方被访问;default类只可以被同一个包内部的类访问。 权限由大到小:public protected default(不写) private 被private修饰的成员只能在本类中访问,外界不能访问 2 set()/get()方法 (1)this关键字 a.可以用来调用变量,方法,构造方法; b.this.xx 理解为调用当前类的xx。 (2)成员变量和局部变量 1)在类中的位置不同 a:成员变量:在类中,方法外 b:局部变量:在方法声明上(形式参数),或者是在方法定义中

2)在内存中的位置不同 a:成员变量:在堆内存 b:局部变量:在栈内存 3)生命周期不同 a:成员变量:随着对象的创建而存在,随着对象的消失而消失 b:局部变量:随着方法调用而存在,随着方法的调用结束而消失 4)初始化值不同 a:成员变量:有默认值 b:局部变量:必须初始化值,否则报错!(在使用它之前,没有初始化) (3)set()/get()方法 当成员变量被private修饰时,不在本类中无法直接访问,便需要set()/get()方法来解决这个问题 3 封装性 封装:是面向对象的第一大特性,所谓封装,就是值对外部不可见(一般而言被private修饰),外部只能通过对象提供的接口(如set()/get()方法)来访问。 封装的好处:a.良好的封装能够减少耦合;

b.类内部的结构可以自己修改,对外部影响不大; c.可以对成员进行更精准的控制(防止出现与事实不符的情况); d.影藏实现细节。 注意:在开发中,类的成员变量全部要进行封装,封装之后通过set()/get()方法访问。 二丶继承extends 1 实现:通过 class Zi extends Fu{} 实现类的继承 (1)子类继承父类,父类中声明的属性,方法,子类都可以获取到; 当父类中有私有的属性方法时,子类同样可以获取到,由于封装性的设计,使得子类不能直接调用访问。 (2)子类除了可以继承父类的结构外,还可以定义直接特有的成员变量,成员方法; (3)Java中类的继承只支持单继承,一个类只能继承一个父类,父类可以有多个子类,但是可以多层继承; (4)子类不能继承父类的构造方法,可以间接的通过super关键字去访问父类的构造方法(super();); 在子类的构造方法中如果没有显示的调用父类的构造方法,会默认调用父类的无参构造(所以最好父类都写有无参构造方法)。 子类继承父类的访问特点:首先父类进行初始化,然后子类进行初始化;多层访问! 2 方法的重写(区别重载) 子类继承父类以后,若父类的方法对子类不适用,那么子类可以对父类方法重写(override) 规则:1)要求子类方法的返回值类型方法名(参数列表)与父类方法一致; 2)子类方法的权限修饰符不能小于父类方法的修饰权限; 3)若父类方法抛异常,那么子类方法抛的异常类型不能大于父类; 注意: a.当子类重写了父类的方法以后,可以用 super.方法调用父类被重写的内容; b.子父类的方法必须同为static或同为非static。 class Fu{ private int i; public Fu(){ //无参构造 super();可以省略 super(); } public Fu(int i){ //有参构造

JAVA面向对象基础测试题-继承-封装-多态等测试题教程文件

J A V A面向对象基础测试题-继承-封装-多 态等测试题

JAVA面向对象基础测试题 提示:本题为第一阶段,JAVA面向对象基础部分练习题,包括对象,类,继承,封装,多态,接口,内部类等等,java核心基础,适合初学者对面向对象基础的知识进行测试,以便查漏补缺。 1. 程序执行的结果是:()。 01 public class Point{ 02 int y = 7; 03 public void step(int y) { 04 y += y; 05 System.out.println(y); 06 } 07 public static void main(String[] args) { 08 Point p = new Point(); 09 p.step(10); 10 } 11 } A.14 B.20 C.10 D.17 正确答案:B解析: 2. 程序的执行结果是:()。 01 public class Question { 02 private int num; 03 public static void main(String [] args){ 04 Question q = new Question();

q.num=13; 06 update(q); 07 System.out.println(q.num); 08 } 09 public static void update(Question q){ 10 q.num=9; 11 } 12 } A.13 B.9 C.0 D.4 正确答案:B解析: 3. 程序执行的结果是:()。 01 public class Answer { 02 public static void main(String[] args) { 03 int score = 20; 04 Answer ans= new Answer(); 05 ans.add(score); 06 System.out.println(" main: score = " + score); 07 } 08 void add(int score) { 09 System.out.println(" add: score=" + score++); 10 } 11

Java为什么要继承、封装和多态

为什么要继承、封装和多态 1,为什么要继承 继承的好处是代码重用.哲学上讲事物都是有共性和特性的.把共性函数代码放入到父类中,把特性函数代码放入到子类中,当然是否共性要以参照点的标准.OO中所谓的抽象我自己理解为哲学中的共性在同一个行业中,他们各业务流程往往有很大的相似性,但往往我们都是到一个项目中就重新写一套流程代码,或者粘贴以前的代码.可能有很多代码都是以前写过的重复代码.造成重复劳动.如果采用继承应该这样,首先在父类中做一个基本上大部分行业项目都必要的简洁的主流程.在子类中针对具体项目的特殊性做主流程充分的完善的补充.这样在每个项目中,只针对项目的特殊性编写代码,大大降低重复劳动.当然根据具体流程的复杂多可以划分多的继承层次,呈现一种继承的树结构,但一定的要保证层次一定要有实际的意义. 2,为什么要封装 高内聚低偶合的思想简单的理解同一模块内的提高内聚,不同模块降低偶合.如果说一个类代表一个模块或是一个业务流,那么A类内部要提高内聚,类的属性可以看成是内的局部变量.提高数据的重用.公共函数尽量能被其他主函数,尽量达到功能内聚.如果说是A类和B类,并且是不同模块(也许是同一个模块下的两个子模块),那么B 是不能使用A的函数和属性的,紧进行数据偶合.封装的作用就体现在这里.

再现实中就项目中经常遇到这种情况,某项业务增加或修改一种类型的业务流,自己本身调试成功了,但是缺影响了此业务下其他的业务流,不得不测试所有得其他原本正常的业务流并不得不针对此做类型判断的补丁,这种补丁很肯能导致程序结构的不合理. 3.为什么要多态 个人认为多态的好处体现在代码的可扩充性,比如一个业务有多个业务流,为了区别不同的类型就的使用判断,那么新添加一个流程就得在过程执行主流程(往往是final,必然是面向过程的)中添加一个”if then”或是重载一个函数 在目前项目中mvc得控制器就是典型的多态.想想如果我们不使用多态那么怎么办?因为对PO对象是新添加的,那么必须针对新的PO 对象在代码中做IF判断,才能用他本身的对象类型指向他.造成过程执行主流程不断的要变更自己的代码. 总结: OO中继承和多态互相依赖又互相矛盾,没有继承就不可能有多态,多态的使用往往又在面向过程的代码中.继承是使子类可以使用父类的功能,而多态使父类能使用子类的功能. OO并非只是在编码阶段来处理,实际上在概要设计,详细设计,数据库设计的时候就应该OO的思想来设计.提高软件可重用性和可扩充性.对于想对一个行业做标准化产品软件而言,很重要.

实验报告(四)继承和多态 (完整代码)

福建农林大学计算机与信息学院实验报告 实验(四)继承和多态 一、实验目的和要求 1.掌握面向对象的继承关系 2.理解面向对象的多态 3.掌握方法的重写 4.掌握接口的实现 二、实验内容和原理 设计一个抽象类Shape,包括2个抽象方法,分别是计算形状的周长和面积。设计具体类Rectangle和Circle,分别表示矩形和圆,它们都是Shapes的子类。使Rectangle和Circle都实现Comparable接口(根据面积比较大小),编写一个通用的排序程序和一个通用的二分查找程序(自己写代码实现),能对这二种类型的数组进行排序并查找指定的对象。 三、实验环境 1.硬件环境: 2.软件环境:JDK1.5 四、算法描述及实验步骤 1.算法描述(可以用类图、流程图、伪代码或源程序描述) package test; import javax.swing.JOptionPane; import java.util.Scanner; public class Test { public static void main(String[] args) { System.out.println("要创建几个圆?:");

Scanner a1 = new Scanner(System.in); int a = a1.nextInt(); System.out.println("总共创建了" + a + "个圆\n请输入各个圆的半径:"); Shape[] circle = new Shape[a]; Scanner input2 = new Scanner(System.in); for (int i = 0; i < a; i++) { circle[i] = new Circle(input2.nextDouble()); } System.out.println("要创建几个矩形?:"); Scanner b2 = new Scanner(System.in); int b = b2.nextInt(); Shape[] rectangle = new Shape[b]; System.out.println("总共创建了" + b + "个矩形\n请依次输入各个矩形的长和宽:"); Scanner c3 = new Scanner(System.in); for (int i = 0; i < b; i++) { rectangle[i] = new Rectangle(c3.nextDouble(), c3.nextDouble()); } Shape.sort(circle); String str1 = ""; for (int i = 0; i < circle.length; i++) { str1 += String.valueOf(i + 1) + circle[i] + "\n"; } System.out.println("您所创建的圆按半径由小到大排序如下:\n" + str1); Shape.sort(rectangle); String str2 = ""; for (int i = 0; i < rectangle.length; i++) { str2 += String.valueOf(i + 1) + rectangle[i] + "\n"; } System.out.println("您所创建的矩形按面积由小到大排序如下:\n" + str2);

第7课件 封装、继承和多态(4学时 19-22)

第七讲义面向对象——类 几种设计模式: 1. 当创建一个对象,若不想让对象的内容(私有成员变量)发生变化,则需要满足以下条件 (1) 所有数据域都是私有的;(2)没有修改方法setMethod;(3)没有一个访问器方法会返回一个指向可变数据域的引用。不可变类/对象例如:String类 2. 为了防止用户创建某个类的对象,则应该定义该类的私有构造方法。例如:Math类 3. 当只允许某个类只能创建一个实例时,称为单例模式。 一、类的封装 方法的抽象;类的抽象;(将方法的实现和使用分开| 将类的实现和使用分开) 类的用户&类的开发者 二、类的继承和多态(2个学时) 继承是java在软件重用方面最重要的特征。能有效避免代码冗余,使系统易于理解和维护、子类继承于父类,UML图表示,次类——超类,或继承类—基类。 当子类继承父类的时候,子类可以继承父类的所有成员跟方法,继承下来不代表可以访问,要访问得看访问控制规则。私有属性也可以继承,不过根据访问控制规则,私有属性虽继承下来却不可以访问的,只有通过public的方法访问继承下来的私有属性。 B继承A类,C继承B类。A类中的私有属性,到了C会怎么样,能继承、访问吗?答案是:如果A中的属性有增加setget方法,可以访问的。举例 public class A { private int a; public int getA(){ return a; } public void setA(int a){ this.a=a; } } public class B extends A{ private int b; public int getB() { return b; } public void setB(int b) { this.b = b; } } public class C extends B { private int c; public int getC() { return c; }

对多态性和继承的理解

C#中的继承符合下列规则: 1、继承是可传递的。如果C从B中派生,B又从A中派生,那么C不仅继承了B中声明的成员,同样也继承了A中的成员。Object 类作为所有类的基类。 2、派生类应当是对基类的扩展。派生类可以添加新的成员,但不能除去已经继承的成员的定义。 3、构造函数和析构函数不能被继承。除此以外的其它成员,不论对它们定义了怎样的访问方式,都能被继承。基类中成员的访问方式 只能决定派生类能否访问它们。 4、派生类如果定义了与继承而来的成员同名的新成员,就可以覆盖已继承的成员。但这并不因为这派生类删除了这些成员,只是不能再 访问这些成员。 5、类可以定义虚方法、虚属性以及虚索引指示器,它的派生类能够重载这些成员,从而实现类可以展示出多态性。 6、派生类只能从一个类中继承,可以通过接吕实现多重继承。 多态性 在C#中,多态性的定义是:同一操作作用于不同的类的实例,不同的类将进行不同的解释,最后产生不同的执行结果。C#支持两种类型的多态性: ●编译时的多态性 编译时的多态性是通过重载来实现的。对于非虚的成员来说,系统在编译时,根据传递的参数、返回的类型等信息决定实现何种操作。 ●运行时的多态性 运行时的多态性就是指直到系统运行时,才根据实际情况决定实现何种操

作。C#中,运行时的多态性通过虚成员实现。 编译时的多态性为我们提供了运行速度快的特点,而运行时的多态性则带来了高度灵活和抽象的特点。 2、实现多态 多态性是类为方法(这些方法以相同的名称调用)提供不同实现方式的能力。多态性允许对类的某个方法进行调用而无需考虑该方法所提供的特定实现。可以用不同的方式实现组件中的多态性: ●接口多态性。 ●继承多态性。 ●通过抽象类实现的多态性。 接口多态性 多个类可实现相同的“接口”,而单个类可以实现一个或多个接口。接口本质上是类需要如何响应的定义。接口描述类需要实现的方法、属性和事件,以及每个成员需要接收和返回的参数类型,但将这些成员的特定实现留给实现类去完成。组件编程中的一项强大技术是能够在一个对象上实现多个接口。每个接口由一小部分紧密联系的方法、属性和事件组成。通过实现接口,组件可以为要求该接口的任何其他组件提供功能,而无需考虑其中所包含的特定功能。这使后续组件的版本得以包含不同的功能而不会干扰核心功能。其他开发人员最常使用的组件功能自然是组件类本身的成员。然而,包含大量成员的组件使用起来可能比较困难。可以考虑将组件的某些功能分解出来,作为私下实现的单独接口。 根据接口来定义功能的另一个好处是,可以通过定义和实现附加接口增量地将功能添加到组件中。优点包括:

封装,继承,多态,抽象,接口

1.1封装 封装是面向对象编程的三大特征之一。封装就是将通过抽象得到的属性和方法相结合,形成一个有机的整体——“类”。封装的目的是增强数据安全性和简化编程,使用者不必了解具体的实现细节,所有对数据的访问和操作都必须通过特定的方法,否则便无法使用,从而达到数据隐藏的目的。 封装是面向对象编程语言对客观世界的模拟,客观世界的属性都是被隐藏在对象内部的,外界不能直接进行操作或者修改。譬如:常见的空调电视机等对象,这些对象都是封装好的,普通人只可以通过对小小的按钮操作来控制这些家电;不可以随意打开设备进行修改对象内容的配置。但是专业人员可以修改这些家电,而我们就是要做这些“专家”;如下图所示。 操作按钮 操作按钮 图1.1.1 封装对象 1.1.1为什么需要封装 通过第一阶段的学习,我们知道类由属性和方法组成,在类的外部通过本类的实例化对象可以自由访问和设置类中的属性信息,这样不利于属性信息的安全,示例1.1就是如此。示例1.1 public class Person { public String name; public int age; public void sayHello(){ System.out.print("你好!"); } } public class Test { public static void main(String[] args) { Person p=new Person(); https://www.wendangku.net/doc/fb11722972.html,="皇帝"; p.age=1000;//属性信息可以直接设置 p.sayHello();

} } 上述代码在第一阶段Java的课程中经常见到,大致一看没什么问题,但是仔细分析过之后会发现:把年龄设置成1000合理吗? 由于Person类的属性都是公有的(public),那也就意味着在Person类的外部,通过Person类的实例化对象可以对这些公有属性任意修改,这就使得我们无法对类的属性进行有效的保护和控制。这属于设计上的缺陷,那能不能避免这种情况呢?这就需要用到下面的封装了。 1.1.2现实生活中的封装 现实生活中封装的例子随处可见,例如药店里出售的胶囊类药品,我们只需要知道这个胶囊有什么疗效,怎么服用就行了,根本不用关心也不可能去操作胶囊的药物成分和生产工艺。再例如家家户户都用的电视机,我们只需要知道电视机能收看电视节目,知道怎么使用就行了,不用关心也不可能去搞清楚电视机内部都有哪些硬件以及是如何组装的。这些都是现实生活中封装的例子。 在刚才的两个例子中,我们可以认为药物成分是胶囊的属性,但是用户不需要也不可能去操作它。我们也可以认为内部硬件是电视机的属性,但是用户也不需要去操作它。这就是现实生活中封装的特征,程序中的封装与此类似。 1.1.3程序中的封装 封装就是:将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部的信息,而是通过该类所提供的方法来实现对内部信息的操作和访问。简而言之,封装就是将类的属性私有化,并提供公有方法访问私有属性的机制,我们看示例1.2。 示例1.2 public class Person{ //将属性使用private修饰,从而隐藏起来 private String name; private int age; public void sayHello() { System.out.print("你好!"); } } public class Test { public static void main(String[] args) { Person p=new Person(); https://www.wendangku.net/doc/fb11722972.html,="杰克"; //编译报错 p.age=1000; //编译报错 p.sayHello(); } }

实验4 类的继承和多态机制

实验4 类的继承和多态机制 一、实验目的 1、掌握类的继承机制; 2、掌握子类对父类构造方法的调用; 3、掌握方法覆盖和方法重载的区别。 二、实验内容 1、定义点类Point、圆类Circle、圆柱体类Cylinder。实现继承关系。 2、定义交通工具类Vehicle,一个小车类Car。实现Car对Vehicle的继承。 三、实验步骤 1、定义点类Point、圆类Circle、圆柱体类Cylinder。实现继承关系。 设计一个表示二维平面上点的类Point,包括表示坐标位置的成员变量x和y,获取和设置x和y值的方法。 设计一个表示二维平面上圆的类Circle,它继承自类Point,还包括表示圆半径的成员变量r、获取和设置r值的方法、计算圆面积的方法。 设计一个表示圆柱体的类Cylinder,它继承自类Circle,还包括表示圆柱体高的成员h、获取和设置h的方法、计算圆柱体表面积的方法、计算圆柱体体积的方法。 建立若干个Cylinder对象,输出其轴心位置坐标、半径、高、表面积及其体积的值。 class Point{ int x; int y; ;public Point(int x,int y){ this.x =x; this.y=y; } public int getX(){ return x; } public int getY(){ return y; } } class Circle extends Point{ double r; final double PI=3.1416; public Circle(int x,int y,double m){ super(x,y); r=m; } public double getR(){ return r; } public double circlearea(){ return PI*r*r;

相关文档
相关文档 最新文档