Index: wp-settings.php
===================================================================
--- wp-settings.php	(revision 13228)
+++ wp-settings.php	(working copy)
@@ -128,6 +128,7 @@
 require( ABSPATH . WPINC . '/media.php' );
 require( ABSPATH . WPINC . '/http.php' );
 require( ABSPATH . WPINC . '/widgets.php' );
+require( ABSPATH . WPINC . '/presentable.php' );
 
 // Load multisite-specific files.
 if ( is_multisite() ) {
Index: wp-includes/classes.php
===================================================================
--- wp-includes/classes.php	(revision 13228)
+++ wp-includes/classes.php	(working copy)
@@ -1696,102 +1696,4 @@
 
 }
 
-// A factory and constructor that upgrades stdClass "rows" to WordPress classes.
-class wp_row {
-	// Factory. Call statically to upgrade a stdClass object to its specialized class: $o = wp_row::get($row).
-	function get($row) {
-		if ( is_a($row, 'wp_row') || is_subclass_of($row, 'wp_row') )
-			return $row;
-
-		if ( is_array($row) )
-			$row = (object) $row;
-
-		$class = 'wp_row';
-		if ( isset($row->post_type) ) {
-			if ( class_exists("wp_" . $row->post_type) )
-				$class = "wp_" . $row->post_type;
-			else
-				$class = "wp_post";
-		} elseif ( isset($row->comment_type) ) {
-			if ( class_exists("wp_" . $row->comment_type) )
-				$class = "wp_" . $row->comment_type;
-			else
-				$class = "wp_comment";
-		}
-
-		if ( function_exists("apply_filters") ) {
-			$filtered_class = apply_filters("wp_row_class", $class, $row);
-			if ( class_exists($filtered_class) )
-				$class = $filtered_class;
-		}
-
-		return call_user_func(array($class, 'get'), $row);
-	}
-
-	function wp_row(&$row) {
-		return $this->__construct($row);
-	}
-
-	function __construct($row) {
-		if ( is_array($row) )
-			$row = (object) $row;
-
-		foreach ( (array) $row as $k => $v )
-			$this->$k = $row->$k;
-	}
-}
-
-class wp_post extends wp_row {
-	// Factory
-	function get($post) {
-		if ( $post = get_post($post) )
-			return new wp_post($post);
-		else
-			return new WP_Error(404, "Post not found.");
-	}
-
-	function id() { return $this->ID; }
-	function post_id() { return $this->ID; }
-	function type_id() { return 'post-' . $this->ID; }
-	function classes($class='') { return join( ' ', get_post_class( $class, $this->id() ) ); }
-
-	function permalink() { return get_permalink($this); }
-	function title() { return get_the_title($this); }
-	function date($format='') { return; }
-	function time($format='') { return get_the_time($format, $this); }
-	function author() { $authordata = get_userdata($this->post_author); return $authordata->display_name; }
-	function content() { return get_content($this); }
-}
-
-class wp_comment extends wp_row {
-	// Factory
-	function get($comment) {
-		if ( $comment = get_comment($comment) )
-			return new wp_comment($comment);
-		else
-			return new WP_Error(404, "Comment not found.");
-	}
-
-	function id() { return $this->comment_ID; }
-	function post_id() { return $this->comment_post_ID; }
-	function type_id() { return 'comment-' . $this->comment_ID; }
-	function classes($class='') { return join( ' ', get_comment_class( $class, $this->id() ) ); }
-
-	function permalink() { return get_comment_link($this); }
-	function title() { return sprintf(__("Comment on %s"), get_the_title($this->post_id())); }
-	function time($format='') { return mysql2date($format?$format:get_option('time_format'), $this->comment_date); }
-	function date($format='') { return date($format?$format:get_option('date_format'), $this->time('U')); }
-	function author() { return $this->comment_author; }
-	function excerpt() { return $this->comment_content; }
-	function content() { return get_comment_content($this); }
-}
-
-function is_post($object) {
-	return is_a('wp_post', $object);
-}
-
-function is_comment($object) {
-	return is_a('wp_comment', $object);
-}
-
 ?>
Index: wp-includes/presentable.php
===================================================================
--- wp-includes/presentable.php	(revision 0)
+++ wp-includes/presentable.php	(revision 0)
@@ -0,0 +1,148 @@
+<?php
+
+// A base interface class with factory methods.
+// Not to become an actual interface, nor an abstract class,
+// because it can be instantiated in a last-ditch effort by the
+// factory method to return something with the necessary methods.
+class WP_Presentable {
+	// A factory method that upgrades stdClass "rows" to their corresponding Presentable classes.
+	// Learn about factories and other design patterns: http://www.ibm.com/developerworks/library/os-php-designptrns/
+	/* public static */ function create($row) {
+		if ( is_a($row, __CLASS__) )
+			return $row;
+
+		if ( is_array($row) )
+			$row = (object) $row;
+
+		if ( isset($row->post_type) ) {
+			if ( empty($row->post_type) )
+				$row->post_type = 'post';
+			$class = __CLASS__ . "_$row->post_type";
+			if ( !class_exists($class) )
+				$class = __CLASS__ . '_post';
+		} elseif ( isset($row->comment_type) ) {
+			if ( empty($row->comment_type) )
+				$row->comment_type = 'comment';
+			$class = __CLASS__ . "_$row->comment_type";
+			if ( !class_exists($class) )
+				$class = __CLASS__ . "_comment";
+		}
+
+		if ( function_exists("apply_filters") ) {
+			$filtered_class = apply_filters("WP_Presentable_class", $class, $row);
+			if ( class_exists($filtered_class) )
+				$class = $filtered_class;
+		}
+
+		return new $class($row);
+	}
+
+	function WP_Presentable($row) {
+		return $this->__construct($row);
+	}
+
+	// Takes an array or object and transfers its named properties to the new instance.
+	function __construct($row) {
+		if ( is_array($row) )
+			$row = (object) $row;
+
+		foreach ( (array) $row as $k => $v )
+			$this->$k = $row->$k;
+	}
+
+	// Interface
+
+	function get_id() { } // post->ID, comment->comment_ID
+	function get_type() { } // post, page, comment, pingback
+	function get_supertype() { } // post, comment
+
+	function get_date($format='') { }
+	function get_time($format='') { }
+
+	function get_url() { } // permalink
+	function get_edit_url() { }
+
+	function get_title() { } // post_title, "Comment on post_title"
+	function get_content() { }
+	function get_excerpt() { }
+
+	function get_author_user_id() { } // int or false
+	function get_author_name() { }
+	function get_author_url() { } // from comment form or user profile
+	function get_author_link() { }
+	function get_author_archive_url() { }
+	function get_author_archive_link() { }
+
+	function get_categories() { }
+	function get_tags() { }
+	function get_terms() { }
+	function get_classes($classes='') { }
+}
+
+class WP_Presentable_post extends WP_Presentable {
+	function get_id() { return $this->ID; }
+	function get_type() { return $this->post_type; }
+	function get_supertype() { return 'post'; }
+
+	function get_date($format='') { }
+	function get_time($format='') { }
+
+	function get_url() { } // permalink
+	function get_edit_url() { }
+
+	function get_title() { return get_the_title($this); } // post_title, "Comment on post_title"
+	function get_content() { }
+	function get_excerpt() { }
+
+	function get_author_user_id() { } // int or false
+	function get_author_name() { }
+	function get_author_url() { } // from comment form or user profile
+	function get_author_link() { }
+	function get_author_archive_url() { }
+	function get_author_archive_link() { }
+
+	function get_categories() { }
+	function get_tags() { }
+	function get_terms() { }
+	function get_classes($classes='') { }
+}
+
+class WP_Presentable_comment extends WP_Presentable {
+	function get_id() { return $this->comment_ID; }
+	function get_type() { return $this->comment_type; }
+	function get_supertype() { return 'comment'; }
+
+	function get_date($format='') { return date($format?$format:get_option('date_format'), $this->get_time('U')); }
+	function get_time($format='') { return mysql2date($format?$format:get_option('time_format'), $this->comment_date); }
+
+	function get_url() { return get_comment_link($this); } // permalink
+	function get_edit_url() { }
+
+	function get_title() { return sprintf(__("Comment on %s"), get_the_title($this->comment_post_ID)); }
+	function get_content() { return get_comment_text($this); }
+	function get_excerpt() { return get_comment_excerpt($this); }
+
+	function get_author_user_id() { } // int or false
+	function get_author_name() { }
+	function get_author_url() { } // from comment form or user profile
+	function get_author_link() { }
+	function get_author_archive_url() { }
+	function get_author_archive_link() { }
+
+	function get_categories() { }
+	function get_tags() { }
+	function get_terms() { }
+	function get_classes($classes='') { }
+
+	function author() { return $this->comment_author; }
+	function excerpt() { return $this->comment_content; }
+}
+
+function is_post($object) {
+	return is_a($object, 'WP_Presentable_post');
+}
+
+function is_comment($object) {
+	return is_a($object, 'WP_Presentable_comment');
+}
+
Index: wp-includes/query.php
===================================================================
--- wp-includes/query.php	(revision 13228)
+++ wp-includes/query.php	(working copy)
@@ -2304,7 +2304,7 @@
 
 		// Turn each row into a classed object, e.g. wp_post, wp_comment.
 		if ( is_array($this->posts) )
-			$this->posts = array_map(array('wp_row', 'get'), $this->posts);
+			$this->posts = array_map(array('WP_Presentable', 'create'), $this->posts);
 
 		if ( !empty($this->posts) && $this->is_comment_feed && $this->is_singular ) {
 			$cjoin = apply_filters('comment_feed_join', '');
