Class Creation
AP Computer Science A Topic 3 7:26 English narration · English + 中文 subtitles burned in
Chapters
Transcript
Here is a student, stored as three loose variables: a name, a year, and a grade.
这里有一个学生,用三个零散的变量存着:姓名、年级和成绩。 这样可以用。
That works. Now add a thousand students. You need three thousand variables, and nothing in the program says which name belongs to which grade — you just have to remember.
现在加到一千个学生:你需要三千个变量,而程序里没有任何东西说明 哪个姓名对应哪个成绩——你只能自己记着。
Wrap them in a class instead, and each student becomes one object that carries its own three values together.
改成用一个类把它们包起来, 每个学生就变成一个对象,自己带着这三个值。
That single idea is what this whole unit is built on.
整个单元就建立在这一个思想上。
Welcome to Unit Three.
欢迎来到第三单元。
You stop using other people's classes and start writing your own: the fields, the constructor, the methods, and the rules about who is allowed to see what.
你不再只是使用别人写好的类,而是开始写自己的类: 属性、构造方法、方法,以及"谁能看到什么"的规则。
Let's begin.
让我们开始吧。
Start with the idea behind all of it.
先说贯穿一切的那个思想。
Abstraction means hiding the complicated details behind a simple interface.
抽象就是把复杂的细节藏在一个简单的接口后面。
You drive a car with a wheel and two pedals. You do not need to know how the engine mixes fuel, and you cannot reach in and break it.
你开车只需要一个方向盘和两个踏板,不需要知道发动机怎么混合燃料, 也没法伸手进去把它弄坏。
That is exactly what a good class does: it hides its data, and offers a short list of methods that are safe to call.
好的类做的正是这件事:它把数据藏起来, 只提供一小串可以安全调用的方法。
Keeping the data private and reaching it only through methods is encapsulation.
把数据设为私有、只通过方法去访问,这就是封装。
Good design means a user of your class can do everything they need without ever knowing how you stored anything.
好的设计意味着: 使用你这个类的人,不需要知道你把东西存成什么样,就能做完所有该做的事。
Design carries responsibility past the code, too.
设计的责任还不止于代码本身。
System reliability — the program doing its job without failing — is something you maximise by careful design and testing.
系统可靠性——程序能不出故障地完成本职工作—— 要靠周密的设计和测试来提高。
Programs affect society and the economy in ways that are both beneficial and harmful.
程序对社会和经济的影响既有好的一面也有坏的一面。
And writing them raises legal and intellectual-property questions: reusing open source code is normal and fine, but respect its licence and give credit.
编写程序还会带来法律和知识产权问题:复用开源代码是正常也是允许的, 但要遵守它的许可证,并注明出处。
Here is the shape every class has.
每个类都有这样的骨架。
Instance variables, also called fields, hold the state — one copy per object, and they are almost always private.
实例变量,也叫字段,保存状态——每个对象各有一份, 而且几乎总是私有的。
The constructor has the same name as the class and no return type at all; it runs once, when the object is created, and its job is to set the fields.
构造方法与类同名,并且完全没有返回类型; 它在对象创建时执行一次,任务是给字段赋值。
Then come the methods, which are public, and which are the only way the outside world is allowed to touch that state.
然后是方法,它们是公有的, 也是外界唯一被允许接触这些状态的途径。
Constructors deserve their own moment, because they break the usual pattern.
构造方法值得单独讲,因为它打破了通常的规律。
Two rules define them: the name must match the class exactly, and there is no return type — not even void.
两条规则定义了它: 名字必须与类完全相同,而且没有返回类型——连 void 都不能写。
Write void by accident and it silently stops being a constructor and becomes an ordinary method.
一不小心写了 void,它就悄悄地不再是构造方法,而变成了普通方法。
The parameters come in, and the constructor's whole job is to copy them into the fields.
参数传进来,构造方法的全部工作就是把它们复制到字段里。
And you can write more than one, as long as their parameter lists differ — that is overloading, and a no-argument constructor is the one that takes nothing and fills in defaults. It lets callers build your object in several convenient ways.
而且你可以写不止一个,只要参数列表不同——这叫重载, 它让调用者能用几种方便的方式来创建你的对象。
Methods come in two everyday flavours.
日常用到的方法分两类。
An accessor gives information out without changing anything — a getter. Its return type is the type of the thing it hands back.
访问器把信息交出来而不改变任何东西——也就是 getter, 它的返回类型就是它交回来的那个东西的类型。
A mutator — a setter — changes the state and usually returns nothing, so its return type is void.
修改器改变状态, 通常什么都不返回,所以返回类型是 void。
Whatever you write, the return type must match what actually comes back: promise an int, and every path through the method has to return an int, or the code will not compile.
不管你怎么写, 返回类型必须与实际返回的东西一致:声明返回 int, 那么方法里每一条路径都必须返回一个 int,否则根本编译不过。
Now the part that surprises people.
现在讲最让人意外的部分。
When you pass an object into a method, you do not pass a copy of the object — you pass a copy of the reference.
当你把一个对象传进方法时, 传的不是对象的副本,而是引用的副本。
Both the caller's name and the parameter now point at the very same object.
调用方的变量名和方法的参数, 现在指向的是同一个对象。
So if the method changes a field, the caller sees that change.
所以如果方法修改了某个字段,调用方能看到这个改动。
But reassigning the parameter — pointing it at a brand-new object — changes nothing for the caller, because only the local copy of the reference moved.
但如果方法让它的参数指向一个全新的对象,调用方什么也看不到, 因为移动的只是引用的那份局部副本。
Trace one, because the exam asks it as a value, not as an explanation.
跟着追一遍,因为考试问的是一个数值,而不是一段解释。
A Student called s has a score of fifty, and we call tweak, passing s in.
一个叫 s 的 Student,分数是五十,我们调用 tweak,把 s 传进去。
Here is the method.
方法是这样的。
Line one calls setScore with one hundred on the parameter.
第一行在参数上调用 setScore,传入一百。
The parameter points at the same object the caller has, so that really does change s.
参数指向的正是调用方持有的那个对象,所以这一行确实改变了 s。
Line two is the one that fools people: it assigns a brand-new Student to the parameter.
第二行才是骗人的那一行:它把一个全新的 Student 赋给参数。
That moves only the method's own copy of the reference — the caller's s still points where it always did.
这只移动了方法自己那份引用副本——调用方的 s 仍然指向原来的地方。
Line three changes only that new object, which nobody outside can reach.
第三行只改变那个新对象,而外面没有任何人能碰到它。
So when the method returns and you ask for the score, the answer is one hundred: the mutation stuck, the reassignment did not.
所以方法返回后,你去问分数,答案是一百: 修改留下了,重新赋值没有。
Two more facts to carry with that.
还要记住两件事。
A primitive is copied by value, so a method can never change the caller's int.
基本类型是按值复制的,所以方法永远改不了调用方的整数。
And a String is immutable, so passing one is always safe — only a mutable object lets a method change something under you.
而字符串是不可变的,所以传字符串总是安全的—— 能让方法在你背后改动的,是可变对象。
Next, the word static.
接下来说 static 这个词。
An instance variable gets one copy per object: every student has their own grade.
实例变量是每个对象各有一份:每个学生都有自己的成绩。
A static variable — a class variable — has exactly one copy shared by the whole class: a single counter of how many students exist. The same split applies to methods.
而静态变量——也叫类变量——整个类只有唯一的一份,被所有对象共享: 比如一个记录共有多少学生的计数器。
A static method belongs to the class and cannot touch instance variables, because there is no particular object for it to look at.
方法也是同样的划分: 静态方法属于类本身,不能碰实例变量,因为它并没有某个具体的对象可看。
Two words control who can see what.
两个词控制着"谁能看到什么"。
Private means only code inside this class can touch it, and that is what you use for fields.
private 表示只有这个类内部的代码才能碰它, 字段就该用它。
Public means anyone can, and that is what you use for the methods you want people to call.
public 表示谁都能用,你希望别人调用的方法就该用它。
Scope is the other half: a local variable lives only inside the block where it was declared and vanishes the moment that block ends, while an instance variable lives as long as the object does.
作用域是另一半:局部变量只在它被声明的那个代码块里存在, 代码块一结束它就消失;而实例变量与对象共存亡。
Why bother?
为什么要这么麻烦?
Because private fields let you change how the class works inside without breaking a single line of anyone else's code.
因为把字段设为私有,你才能改动类的内部实现,而不弄坏别人代码里的任何一行。
Which leaves one small word that fixes a very common problem.
最后剩下一个小小的关键字,用来解决一个非常常见的问题。
Inside a constructor it is natural to name the parameter the same as the field — name and name.
在构造方法里,很自然会把参数取成和字段一样的名字——都叫 name。
But then the parameter shadows the field: every plain use of that word means the parameter, so assigning name to name does nothing at all.
但这样参数就把字段"遮住"了:单写这个名字都指参数, 所以把 name 赋给 name 其实什么都没做。
Write this dot name on the left, and you are explicitly talking about the field.
在左边写上 this 点 name, 你就明确地在说那个字段。
In general, this is a reference to the current object — the one the method was called on.
一般来说,this 永远指"方法被调用时所在的那个对象"。
Three marks students throw away.
三个学生常丢的分。
First, a constructor has no return type at all — writing void turns it into an ordinary method and your object never gets initialised.
第一,构造方法完全没有返回类型—— 写了 void 就把它变成了普通方法,你的对象也就永远不会被初始化。
Second, make fields private and methods public; the exam asks you to justify it, and the answer is that the class can then change inside without breaking anyone.
第二,字段设为私有、方法设为公有;考试会要你说明理由, 理由是这样类的内部就能改动而不弄坏任何人的代码。
Third, a static method cannot use instance variables, because there is no particular object for it to read them from.
第三,静态方法不能使用实例变量,因为它没有某个具体的对象可以从中读取。
Two more things the exam expects you to read rather than write: trace a recursive method by finding its base case first, then following each call to its return value; and recognise the inheritance words — superclass, subclass, overriding.
考试还期望你能读懂、而不一定要自己写出的两件事:追踪递归方法时, 先找到它的基线情形,再顺着每一次调用去看它的返回值; 以及认识继承的那几个词——超类、子类、重写。