一:首先,一个简单的继承实例

首先是创建一个父类Person:

function Person(name) {
this.name = name;
} Person.prototype.getName = function() {
return this.name;
}
下面是创建一个子类Author,用于继承Person:
分两步,第一步继承父类的属性,第二部继承父类的公共方法

function Author(name, books) {
Person.call(this, name); // 通过这一行代码可以继承父类的属性
this.books = books; // 子类增添自己的属性
} Author.prototype = new Person(); // 继承父类方法的第一行代码
Author.prototype.constructor = Author; // 继承父类方法的第二行代码
Author.prototype.getBooks = function() { // 子类增添自己的方法
return this.books;
};

这样就完成了一个简单的继承

二:编写一个extend函数来简化类的声明

extend函数:
function extend(subClass, superClass) {
var F = function() {};
F.prototype = superClass.prototype;
subClass.prototype = new F();
subClass.prototype.constructor = subClass;
}

extend的函数作用有两个,一为简化代码,二就是使继承父类方法的时候不用运行父类的构造函数然后Author这个子类的定义就变成了这样:

function Author(name, books) {
Person.call(this, name);
this.books = books;
}
extend(Author, Person); Author.prototype.getBooks = function() {
return this.books;
};

到目前为止,我们要调用超类的方法,是要以Person开头来调用的(例如:Person.call。。。。等),如果我们想要通过Author开头来调用父类的方法,我们就要对extend函数做一些改动改进的extend函数:

function extend(subClass, superClass) {
var F = function() {};
F.prototype = superClass.prototype;
subClass.prototype = new F();
subClass.prototype.constructor = subClass; subClass.superclass = superClass.prototype;
if(superClass.prototype.constructor == Object.prototype.constructor) {
superClass.prototype.constructor = superClass;
}
}

利用上面的倒数第五行代码,我们就可以使子类可以调用通过Author.这种方法调用父类的方法了(这样做是为了不让Person出现在Author类的定义中),然后我们就可以把Author的定义改成以下:

function Author(name, books) {
Author.superclass.constructor.call(this, name);
this.books = books;
}
extend(Author, Person); Author.prototype.getBooks = function() {
return this.books;
}; Author.prototype.getName = function() {
var name = Author.superclass.getName.call(this);
return name + ', Author of ' + this.getBooks().join(', ');
};

这样的话,Author的定义中,除了extend函数中有出现过Person,其他地方都没有出现Person了~三: 原型式继承接下来,我们使用原型式继承来重新设计Person和Author:首先,clone函数(按照书上的顺序,这个可以先不看):

function clone(object) {
function F() {}
F.prototype = object;
return new F;
}

步骤一(定义Person原型):

var Person = {
name: 'default name',
getName: function() {
return this.name;
}
};

步骤二(通过原型式继承,创建Author原型):

var Author = clone(Person);
Author.books = []; // Default value.
Author.getBooks = function() {
return this.books;
}

步骤三(使用):

var author = [];

author[] = clone(Author);
author[].name = 'Dustin Diaz';
author[].books = ['JavaScript Design Patterns']; author[] = clone(Author);
author[].name = 'Ross Harmes';
author[].books = ['JavaScript Design Patterns']; author[].getName();
author[].getBooks();

通过这样的方法,传统意义的类就变成这样一个个的对象了!(虽然在javascript中类也是对象。。。)这种方法的特点就是所有对象共用一个对象原型,其实就是这么简单。但是这导致的一个问题就是读和写的不对等。下面例子说明这个问题:

var authorClone = clone(Author);
alert(authorClone.name); // 调用的其实是Person.name
// 所以输出的是字符串'default name'.
authorClone.name = 'new name'; // 这样做其实就是在自己的对象中创建一个name属性
alert(authorClone.name); // 这样再使用name属性的时候,就会变成使用自己的name属性,而不是原型上的Person.name了
// 所以这时候的值是'new name'
authorClone.books.push('new book'); // 对于数组也就是一样的道理,这行代码没有创建自身的books属性,等于直接操作原型里面的属性,所以就会导致原型的默认值编程‘new book’了,这会作用到其他使用原型继承的其他对象当中
authorClone.books = []; // 所以解决的方法就是在自身的对象中新建一个books数组
authorClone.books.push('new book'); // 然后再进行对数组的操作
提示,通过hasOwnProperty可以去分对象的实际成员和它继承而来的成员
此外,上述的这种情况对于拥有对象属性的原型来说也是一样,其实我们也可以用同一种办法来解决,例如下面这个实例:


var CompoundObject = {
string1: 'default value',
childObject: {
bool: true,
num:
}
} var compoundObjectClone = clone(CompoundObject); // 这样做的话就会破坏原型的默认值了
compoundObjectClone.childObject.num = ; // 这个解决方法和上面数组那个一样,在自身的原型里面创建一个心的childObject对象
compoundObjectClone.childObject = {
bool: true,
num:
};

但是,问题又来了,我想要知道默认值的情况下创建自身的childObject对象要怎样做呢?下面就是一种解决方法,利用工厂方法来创建自身的childObject


var CompoundObject = {};
CompoundObject.string1 = 'default value',
CompoundObject.createChildObject = function() {//这个函数是关键,返回一份副本
return {
bool: true,
num:
}
};
CompoundObject.childObject = CompoundObject.createChildObject();//这里就在原型里面先获取一次这个对象副本,原型就有了childObject属性 var compoundObjectClone = clone(CompoundObject);
compoundObjectClone.childObject = CompoundObject.createChildObject();//这里就创建新对象自己的childObject属性
compoundObjectClone.childObject.num = 5;

四: 类式继承和原型式继承的对比类式继承的优点就是很多人都知道原型式继承的优点就是代码简洁,并且节约内存(因为如果克隆出来的对象不新建自己的属性的话,那么就只有原型上的一份公共副本而已)五: 继承与封装

如果要继承的话,最好父类使用门户大开方法

六: 掺元类javascript中只能继承一个父类,所以如有一些不需要严格继承,但是很多类都用到的方法,我们就通过扩充的方式让这些类共享这些方法,例子:一个类(其实就是包含一个简单的toJSONString方法):

var Mixin = function() {};
Mixin.prototype = {
serialize: function() {
var output = [];
for(key in this) {
output.push(key + ': ' + this[key]);
}
return output.join(', ');
}
};

我们很多类都需要用到上面这个类的serialize方法,所以我们就用扩充函数来扩充需要这个方法的类(扩充函数的具体代码下面会给出):

augment(Author, Mixin);

让后就可以使用了:

var author = new Author('Ross Harmes', ['JavaScript Design Patterns']);
var serializedString = author.serialize();

现在给出augment函数的具体代码:

function augment(receivingClass, givingClass) {
for(methodName in givingClass.prototype) {
if(!receivingClass.prototype[methodName]) {
receivingClass.prototype[methodName] = givingClass.prototype[methodName];
}
}
}

其实就是遍历有没有同名的方法,没有的话就添加到要扩展的类中。如果想要只扩展某些方法,而不是全部方法,那么就改进一下augment函数:

function augment(receivingClass, givingClass) {
if(arguments[]) { // Only give certain methods.
for(var i = , len = arguments.length; i < len; i++) {
receivingClass.prototype[arguments[i]] = givingClass.prototype[arguments[i]];
}
}
else { // Give all methods.
for(methodName in givingClass.prototype) {
if(!receivingClass.prototype[methodName]) {
receivingClass.prototype[methodName] = givingClass.prototype[methodName];
}
}
}
}

改进的augment函数可以选传第三个以后的参数,这些参数都是方法名。然后函数会检测有没有选传的参数,如果有的话就只扩展与这些参数同名的方法。否则扩展全部方法。七: 示例:就地编辑

下面就是使用一个例子,来演示上所说的三种方法。
例子说明:假设你的任务就是编写一个用于创建和管理就地编辑域的可重用的模块化API(就地编辑是指网页上的一段普通文本被点击后就变成一个配有一些按钮的表单域,以便用户对这段文本进行编辑)。使用这个API,用户应该能够为对象分配一个唯一的ID值,能够为它提供一个默认值,并且能够指定其在页面上的目标位置。用户还应该在任何时候都可以访问到这个域的当前值,并且可以选择具体使用的编辑域(比如多行文本框或单行文本框)。
也就是说,平时是这个样子的:

点击之后会变成这样在的:   

文本框中填写"改变文本",save后:

接下来,我们的需求更改了,要把input框变成textarea框,怎么办了?也就是说
点击之后要变成这样子:



方法一:类式继承解决方案
首先创建一个父类EditInPlaceField以及演示它的使用:
<html>

<head>
<meta http-equiv="charset" content="utf-8"></head> <body>
<script>
//类的定义
function EditInPlaceField(id, parent, value) {
this.id = id;
this.parentElement = parent;
this.value = value || 'default value'; this.createElements(this.id);
this.attachEvents();
} EditInPlaceField.prototype = {
createElements: function (id) {
this.containerElement = document.createElement('div');
this.parentElement.appendChild(this.containerElement); this.staticElement = document.createElement('span');
this.containerElement.appendChild(this.staticElement);
this.staticElement.innerHTML = this.value; this.fieldElement = document.createElement('input');
this.fieldElement.type = 'text';
this.fieldElement.value = this.value;
this.containerElement.appendChild(this.fieldElement); this.saveButton = document.createElement('input');
this.saveButton.type = 'button';
this.saveButton.value = 'Save';
this.containerElement.appendChild(this.saveButton); this.cancelButton = document.createElement('input');
this.cancelButton.type = 'button';
this.cancelButton.value = 'Cancel';
this.containerElement.appendChild(this.cancelButton); this.convertToText();
},
attachEvents: function () {
var that = this;
this.staticElement.addEventListener('click', function () {
that.convertToEditable();
},false);
this.saveButton.addEventListener('click', function () {
that.save();
},false);
this.cancelButton.addEventListener('click', function () {
that.cancel();
},false);
},
convertToEditable: function () {
this.staticElement.style.display = 'none';
this.fieldElement.style.display = 'inline';
this.saveButton.style.display = 'inline';
this.cancelButton.style.display = 'inline'; this.setValue(this.value);
},
save: function () {
this.value = this.getValue();
this.convertToText();
},
cancel: function () {
this.convertToText();
},
convertToText: function () {
this.fieldElement.style.display = 'none';
this.saveButton.style.display = 'none';
this.cancelButton.style.display = 'none';
this.staticElement.style.display = 'inline'; this.setValue(this.value);
}, setValue: function (value) {
this.fieldElement.value = value;
this.staticElement.innerHTML = value;
},
getValue: function () {
return this.fieldElement.value;
}
} //类的使用
var body = document.body;
var titleClassical = new EditInPlaceField('titleClassical', body, 'Title Here');
</script></body> </html>

接下来,就演示如何通过继承来把input装换成textarea框,增添的代码如下:

        function extend(subClass, superClass) {
var F = function () {};
F.prototype = superClass.prototype;
subClass.prototype = new F();
subClass.prototype.constructor = subClass; subClass.superclass = superClass.prototype;
if (superClass.prototype.constructor == Object.prototype.constructor) {
superClass.prototype.constructor = superClass;
}
} //继承
function EditInPlaceArea(id, parent, value) {
EditInPlaceArea.superclass.constructor.call(this, id, parent, value);
};
extend(EditInPlaceArea, EditInPlaceField); EditInPlaceArea.prototype.createElements = function (id) {
this.containerElement = document.createElement('div');
this.parentElement.appendChild(this.containerElement); this.staticElement = document.createElement('p');
this.containerElement.appendChild(this.staticElement);
this.staticElement.innerHTML = this.value; this.fieldElement = document.createElement('textarea');
this.fieldElement.value = this.value;
this.containerElement.appendChild(this.fieldElement); this.saveButton = document.createElement('input');
this.saveButton.type = 'button';
this.saveButton.value = 'Save';
this.containerElement.appendChild(this.saveButton); this.cancelButton = document.createElement('input');
this.cancelButton.type = 'button';
this.cancelButton.value = 'Cancel';
this.containerElement.appendChild(this.cancelButton); this.convertToText();
};
EditInPlaceArea.prototype.convertToEditable = function () {
this.staticElement.style.display = 'none';
this.fieldElement.style.display = 'block';
this.saveButton.style.display = 'inline';
this.cancelButton.style.display = 'inline'; this.setValue(this.value);
};
EditInPlaceArea.prototype.convertToText = function () {
this.fieldElement.style.display = 'none';
this.saveButton.style.display = 'none';
this.cancelButton.style.display = 'none';
this.staticElement.style.display = 'block'; this.setValue(this.value);
}; var AreaObject = new EditInPlaceArea('AreaObject', body, '多行文本框默认值');

继承之后,再重写相应的方法,就完成了所有需求了。


方法二:原型式继承解决方案
第一步:
<html>

<head>
<meta http-equiv="charset" content="utf-8"></head> <body>
<script>
function clone(object) {
function F() {}
F.prototype = object;
return new F;
} var EditInPlaceField = {
configure: function (id, parent, value) {
this.id = id;
this.value = value || 'default value';
this.parentElement = parent; this.createElements(this.id);
this.attachEvents();
},
createElements: function (id) {
this.containerElement = document.createElement('div');
this.parentElement.appendChild(this.containerElement); this.staticElement = document.createElement('span');
this.containerElement.appendChild(this.staticElement);
this.staticElement.innerHTML = this.value; this.fieldElement = document.createElement('input');
this.fieldElement.type = 'text';
this.fieldElement.value = this.value;
this.containerElement.appendChild(this.fieldElement); this.saveButton = document.createElement('input');
this.saveButton.type = 'button';
this.saveButton.value = 'Save';
this.containerElement.appendChild(this.saveButton); this.cancelButton = document.createElement('input');
this.cancelButton.type = 'button';
this.cancelButton.value = 'Cancel';
this.containerElement.appendChild(this.cancelButton); this.convertToText();
},
attachEvents: function () {
var that = this;
this.staticElement.addEventListener('click', function () {
that.convertToEditable();
}, false);
this.saveButton.addEventListener('click', function () {
that.save();
}, false);
this.cancelButton.addEventListener('click', function () {
that.cancel();
}, false);
}, convertToEditable: function () {
this.staticElement.style.display = 'none';
this.fieldElement.style.display = 'inline';
this.saveButton.style.display = 'inline';
this.cancelButton.style.display = 'inline'; this.setValue(this.value);
}, save: function () {
this.value = this.getValue();
this.convertToText();
}, cancel: function () {
this.convertToText();
},
convertToText: function () {
this.fieldElement.style.display = 'none';
this.saveButton.style.display = 'none';
this.cancelButton.style.display = 'none';
this.staticElement.style.display = 'inline'; this.setValue(this.value);
}, setValue: function (value) {
this.fieldElement.value = value;
this.staticElement.innerHTML = value;
},
getValue: function () {
return this.fieldElement.value;
}
}; var body = document.body;
var titlePrototypal = clone(EditInPlaceField);
titlePrototypal.configure('titlePrototypal ', body, 'Title Here');
</script></body> </html>

第二步继承,添加的代码:

        var EditInPlaceArea = clone(EditInPlaceField);

        EditInPlaceArea.createElements = function (id) {
this.containerElement = document.createElement('div');
this.parentElement.appendChild(this.containerElement); this.staticElement = document.createElement('p');
this.containerElement.appendChild(this.staticElement);
this.staticElement.innerHTML = this.value; this.fieldElement = document.createElement('textarea');
this.fieldElement.value = this.value;
this.containerElement.appendChild(this.fieldElement); this.saveButton = document.createElement('input');
this.saveButton.type = 'button';
this.saveButton.value = 'Save';
this.containerElement.appendChild(this.saveButton); this.cancelButton = document.createElement('input');
this.cancelButton.type = 'button';
this.cancelButton.value = 'Cancel';
this.containerElement.appendChild(this.cancelButton); this.convertToText();
};
EditInPlaceArea.convertToEditable = function () {
this.staticElement.style.display = 'none';
this.fieldElement.style.display = 'block';
this.saveButton.style.display = 'inline';
this.cancelButton.style.display = 'inline'; this.setValue(this.value);
};
EditInPlaceArea.convertToText = function () {
this.fieldElement.style.display = 'none';
this.saveButton.style.display = 'none';
this.cancelButton.style.display = 'none';
this.staticElement.style.display = 'block'; this.setValue(this.value);
}; //使用
var editInPlaceArea = clone(EditInPlaceArea);
editInPlaceArea.configure('editInPlaceArea ', body, 'editInPlaceArea');

这样就完成了,其实,相对于第一种方法,改动是很少的~。


方法三:掺元类解决方案
先把扩展类复制进代码中:
function augment(receivingClass, givingClass) {
if (arguments[]) { // Only give certain methods.
for (var i = , len = arguments.length; i < len; i++) {
receivingClass.prototype[arguments[i]] = givingClass.prototype[arguments[i]];
}
} else { // Give all methods.
for (methodName in givingClass.prototype) {
if (!receivingClass.prototype[methodName]) {
receivingClass.prototype[methodName] = givingClass.prototype[methodName];
}
}
}
}

然后创建一个包含了所有要共享的方法的类:

var EditInPlaceMixin = function() {};
EditInPlaceMixin.prototype = {
createElements: function(id) {
this.containerElement = document.createElement('div');
this.parentElement.appendChild(this.containerElement); this.staticElement = document.createElement('span');
this.containerElement.appendChild(this.staticElement);
this.staticElement.innerHTML = this.value; this.fieldElement = document.createElement('input');
this.fieldElement.type = 'text';
this.fieldElement.value = this.value;
this.containerElement.appendChild(this.fieldElement); this.saveButton = document.createElement('input');
this.saveButton.type = 'button';
this.saveButton.value = 'Save';
this.containerElement.appendChild(this.saveButton); this.cancelButton = document.createElement('input');
this.cancelButton.type = 'button';
this.cancelButton.value = 'Cancel';
this.containerElement.appendChild(this.cancelButton); this.convertToText();
}, attachEvents: function() {
var that = this;
this.staticElement.addEventListener('click', function() {
that.convertToEditable();
}, false);
this.saveButton.addEventListener('click', function() {
that.save();
}, false);
this.cancelButton.addEventListener('click', function() {
that.cancel();
}, false);
}, convertToEditable: function() {
this.staticElement.style.display = 'none';
this.fieldElement.style.display = 'inline';
this.saveButton.style.display = 'inline';
this.cancelButton.style.display = 'inline'; this.setValue(this.value);
}, save: function() {
this.value = this.getValue();
this.convertToText();
}, cancel: function() {
this.convertToText();
},
convertToText: function() {
this.fieldElement.style.display = 'none';
this.saveButton.style.display = 'none';
this.cancelButton.style.display = 'none';
this.staticElement.style.display = 'inline'; this.setValue(this.value);
}, setValue: function(value) {
this.fieldElement.value = value;
this.staticElement.innerHTML = value;
},
getValue: function() {
return this.fieldElement.value;
}
};

下一步就是创建一个EditInPlaceField类,然后扩展它

function EditInPlaceField(id, parent, value) {
this.id = id;
this.value = value || 'default value';
this.parentElement = parent; this.createElements(this.id);
this.attachEvents();
};
augment(EditInPlaceField, EditInPlaceMixin);

像第一种方法一样使用

var body = document.body;
var titleClassical = new EditInPlaceField('titleClassical', body, 'Title Here');

将input框变成textarea的做法如下:首先创建EditInPlaceArea构造方法:

        function EditInPlaceArea(id, parent, value) {
this.id = id;
this.value = value || 'default value';
this.parentElement = parent; this.createElements(this.id);
this.attachEvents();
};

添加要重写的方法:

        EditInPlaceArea.prototype.createElements = function (id) {
this.containerElement = document.createElement('div');
this.parentElement.appendChild(this.containerElement); this.staticElement = document.createElement('p');
this.containerElement.appendChild(this.staticElement);
this.staticElement.innerHTML = this.value; this.fieldElement = document.createElement('textarea');
this.fieldElement.value = this.value;
this.containerElement.appendChild(this.fieldElement); this.saveButton = document.createElement('input');
this.saveButton.type = 'button';
this.saveButton.value = 'Save';
this.containerElement.appendChild(this.saveButton); this.cancelButton = document.createElement('input');
this.cancelButton.type = 'button';
this.cancelButton.value = 'Cancel';
this.containerElement.appendChild(this.cancelButton); this.convertToText();
};
EditInPlaceArea.prototype.convertToEditable = function () {
this.staticElement.style.display = 'none';
this.fieldElement.style.display = 'block';
this.saveButton.style.display = 'inline';
this.cancelButton.style.display = 'inline'; this.setValue(this.value);
};
EditInPlaceArea.prototype.convertToText = function () {
this.fieldElement.style.display = 'none';
this.saveButton.style.display = 'none';
this.cancelButton.style.display = 'none';
this.staticElement.style.display = 'block'; this.setValue(this.value);
};

最后才是扩展:

augment(EditInPlaceArea, EditInPlaceMixin);

使用:

var AreaObject = new EditInPlaceArea('AreaObject', body, '多行文本框默认值');

其实这种方法用在这个例子上是不是很适合的,因为上面那两个类都很相似,导致要先重写一些方法再扩展。












《javascript设计模式》笔记之第四章:继承的更多相关文章

  1. Javascript设计模式笔记

    Javascript是越来越厉害了,一统前后端开发.于是最近把设计模式又看了一遍,顺便做了个笔记,以方便自己和他人共同学习. 笔记连载详见:http://www.meteorcn.net/wordpr ...

  2. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第四章:Direct 3D初始化

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第四章:Direct 3D初始化 学习目标 对Direct 3D编程在 ...

  3. 【NPDP笔记】第四章 文化组织与团队

    此为临时链接,仅用于预览,将在短期内失效.关闭 [NPDP笔记]第四章 文化组织与团队 小康 小康哥的产品之路 9月6日 4.1 文化和氛围对创新的重要性 文化:信念,价值观,假设,与期望 氛围:直接 ...

  4. [书籍翻译] 《JavaScript并发编程》第四章 使用Generators实现惰性计算

    本文是我翻译<JavaScript Concurrency>书籍的第四章 使用Generators实现惰性计算,该书主要以Promises.Generator.Web workers等技术 ...

  5. Java程序猿JavaScript学习笔记(2——复制和继承财产)

    计划和完成在这个例子中,音符的以下序列: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaSc ...

  6. win32多线程程序设计笔记(第四章下)

    上一笔记讲了同步机制中的临界区域(Critical Sections).互斥器(Mutexes),下面介绍同步机制中的另外两种. 信号量(Semaphores) 举个例子: 现在有人要租车,接待他的代 ...

  7. 05 技术内幕 T-SQL 查询读书笔记(第四章)

    第四章 子查询:在外部查询内嵌套的内部查询(按照期望值的数量分为,标量子查询 scalar subqueries,多值子查询multivalued subqueries)(按照子查询对外部查询的依赖性 ...

  8. javascript - 工作笔记 (事件四)

    在javascript - 工作笔记 (事件绑定二)篇中,我将事件的方法做了简单的包装,  JavaScript Code  12345   yx.bind(item, "click&quo ...

  9. Linux内核分析 读书笔记 (第四章)

    第四章 进程调度 调度程序负责决定将哪个进程投入运行,何时运行以及运行多长时间.进程调度程序可看做在可运行态进程之间分配有限的处理器时间资源的内核子系统.只有通过调度程序的合理调度,系统资源才能最大限 ...

  10. 《深入理解java虚拟机》读书笔记三——第四章

    第四章 虚拟机性能监控与故障处理工具 1.JDK命令行工具 jps命令: 作用:列出正在运行的虚拟机进程. 格式:jps [option] [hostid] 选项:-q 只输出LVMID(Local ...

随机推荐

  1. 调试windows服务最简单的方法之一

    先看一下这段启动代码: using System; using System.Collections.Generic; using System.Linq; using System.ServiceP ...

  2. js 改变对象的引用地址

    在业务处理中我们经常会碰到列表中有编辑和新增按钮,为了能够提高代码的公用性,我们经常会使用同一组件处理. 这样会出现一个问题就是编辑的时候直接把对象传过去,直接赋值,引用地址是同一个,所以不管修改了那 ...

  3. win10 下安装linux子系统

    一.开发人员选项 打开控制面板->程序与功能->启用或关闭windows功能 勾选    [适用于linux的windows子系统]    选项 打开win10设置 找到更新与安全 启动开 ...

  4. 使用WebBrowser自动登录阿里妈妈网站

    窗体上放一个WebBrowser,其Url属性设置为http://www.alimama.com/membersvc/member/login.htm,其他属性为默认 再放一个Button,默认 Bu ...

  5. bzoj 5072 [Lydsy1710月赛]小A的树——树形dp

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5072 发现对于每个子树,黑点个数确定时,连通块的大小取值范围一定是一段区间:所以考虑只最小化 ...

  6. bzoj 4712 洪水 —— 动态DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4712 设 f[x] = min(∑f[u] , a[x]),ls = ∑f[lson] 矩阵 ...

  7. UVA562(01背包均分问题)

    Dividing coins Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Descriptio ...

  8. CSS:CSS 单位

    ylbtech-CSS:CSS 单位 1.返回顶部 1. 尺寸 单位 描述 % 百分比 in 英寸 cm 厘米 mm 毫米 em 1em 等于当前的字体尺寸. 2em 等于当前字体尺寸的两倍. 例如, ...

  9. python 进程和线程的区别

    1.开进程的开销远大于开线程 import time from threading import Thread from multiprocessing import Process def piao ...

  10. 3-C++程序的结构1.2

    对象的生存周期 可以分为静态生存周期和动态生存周期 1.静态生存周期 如果对象的生存期与程序的运行期相同,我们称它具有静态生存期.在文件作用域中声明的对象都具有静态生存期的.如果要在函数的块中声明具有 ...