diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index 6189c72..81f3914 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -11,6 +11,7 @@
  */
 
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\user\EntityAuthorInterface;
 use Drupal\Core\Entity\EntityChangedInterface;
 use Drupal\comment\CommentInterface;
 use Drupal\comment\Entity\Comment;
@@ -950,18 +951,22 @@ function comment_entity_insert(EntityInterface $entity) {
       'last_comment_uid',
       'comment_count'
     ));
+    $execute_query = FALSE;
     foreach ($fields as $field_name => $detail) {
       // Skip fields that entity does not have.
       if (!$entity->hasField($field_name)) {
         continue;
       }
       // There is at least one comment field, the query needs to be executed.
-      // @todo Use $entity->getAuthorId() after https://drupal.org/node/2078387
-      if ($entity->hasField('uid')) {
-        $last_comment_uid = $entity->get('uid')->value;
+      $execute_query = TRUE;
+      // Get the user ID from the entity if it is set, or default to the
+      // currently logged in user.
+      if ($entity instanceof EntityAuthorInterface) {
+        $last_comment_uid = $entity->getAuthorId();
       }
-      else {
-        // Default to current user when entity does not have a uid property.
+      if (!isset($last_comment_uid)) {
+        // Default to current user when entity does not implement
+        // EntityAuthorInterface or author is not set.
         $last_comment_uid = \Drupal::currentUser()->id();
       }
       // Default to REQUEST_TIME when entity does not have a changed property.
@@ -980,7 +985,9 @@ function comment_entity_insert(EntityInterface $entity) {
         'comment_count' => 0,
       ));
     }
-    $query->execute();
+    if ($execute_query) {
+      $query->execute();
+    }
   }
 }
 
@@ -1108,7 +1115,7 @@ function comment_user_cancel($edit, $account, $method) {
     case 'user_cancel_reassign':
       $comments = entity_load_multiple_by_properties('comment', array('uid' => $account->id()));
       foreach ($comments as $comment) {
-        $comment->uid->target_id = 0;
+        $comment->setAuthorId(0);
         $comment->save();
       }
       break;
@@ -1300,7 +1307,7 @@ function comment_preview(CommentInterface $comment, array &$form_state) {
     }
 
     if (!empty($account) && $account->isAuthenticated()) {
-      $comment->uid->target_id = $account->id();
+      $comment->setAuthorId($account->id());
       $comment->name->value = check_plain($account->getUsername());
     }
     else {
@@ -1371,7 +1378,7 @@ function comment_preprocess_block(&$variables) {
  */
 function comment_prepare_author(CommentInterface $comment) {
   // The account has been pre-loaded by CommentViewBuilder::buildContent().
-  $account = $comment->uid->entity;
+  $account = $comment->getAuthor();
   if (empty($account->uid->value)) {
     $account = entity_create('user', array('uid' => 0, 'name' => $comment->name->value, 'homepage' => $comment->homepage->value));
   }
@@ -1493,12 +1500,11 @@ function template_preprocess_comment(&$variables) {
   if ($variables['status'] != 'published') {
     $variables['attributes']['class'][] = $variables['status'];
   }
-  if (!$comment->uid->target_id) {
+  if (!$comment->getAuthorId()) {
     $variables['attributes']['class'][] = 'by-anonymous';
   }
   else {
-    // @todo Use $entity->getAuthorId() after https://drupal.org/node/2078387
-    if ($commented_entity->hasField('uid') && $comment->uid->target_id == $commented_entity->get('uid')->value) {
+    if ($commented_entity instanceof EntityAuthorInterface && $comment->getAuthorId() == $commented_entity->getAuthorId()) {
       $variables['attributes']['class'][] = 'by-' . $commented_entity->entityType() . '-author';
     }
   }
@@ -1506,7 +1512,7 @@ function template_preprocess_comment(&$variables) {
   $variables['attributes']['class'][] = 'clearfix';
 
   // Add comment author user ID. Necessary for the comment-by-viewer library.
-  $variables['attributes']['data-comment-user-id'] = $comment->uid->value;
+  $variables['attributes']['data-comment-user-id'] = $comment->getAuthorId();
 
   $variables['content_attributes']['class'][] = 'content';
 }
diff --git a/core/modules/comment/comment.tokens.inc b/core/modules/comment/comment.tokens.inc
index eab4d3e..6702d24 100644
--- a/core/modules/comment/comment.tokens.inc
+++ b/core/modules/comment/comment.tokens.inc
@@ -142,13 +142,13 @@ function comment_tokens($type, $tokens, array $data = array(), array $options =
           break;
 
         case 'name':
-          $name = ($comment->uid->target_id == 0) ? \Drupal::config('user.settings')->get('anonymous') : $comment->name->value;
+          $name = ($comment->getAuthorId() == 0) ? \Drupal::config('user.settings')->get('anonymous') : $comment->name->value;
           $replacements[$original] = $sanitize ? filter_xss($name) : $name;
           break;
 
         case 'mail':
-          if ($comment->uid->target_id != 0) {
-            $mail = $comment->uid->entity->getEmail();
+          if ($comment->getAuthorId() != 0) {
+            $mail = $comment->getAuthor()->getEmail();
           }
           else {
             $mail = $comment->mail->value;
@@ -244,7 +244,7 @@ function comment_tokens($type, $tokens, array $data = array(), array $options =
       $replacements += $token_service->generate('comment', $parent_tokens, array('comment' => $parent), $options);
     }
 
-    if (($author_tokens = $token_service->findwithPrefix($tokens, 'author')) && $account = $comment->uid->entity) {
+    if (($author_tokens = $token_service->findwithPrefix($tokens, 'author')) && $account = $comment->getAuthor()) {
       $replacements += $token_service->generate('user', $author_tokens, array('user' => $account), $options);
     }
   }
diff --git a/core/modules/comment/lib/Drupal/comment/CommentAccessController.php b/core/modules/comment/lib/Drupal/comment/CommentAccessController.php
index 800991f..1ff84c1 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentAccessController.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentAccessController.php
@@ -28,7 +28,7 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A
         break;
 
       case 'update':
-        return ($account->id() && $account->id() == $entity->uid->value && $entity->status->value == COMMENT_PUBLISHED && user_access('edit own comments', $account)) || user_access('administer comments', $account);
+        return ($account->id() && $account->id() == $entity->getAuthorId() && $entity->status->value == COMMENT_PUBLISHED && user_access('edit own comments', $account)) || user_access('administer comments', $account);
         break;
 
       case 'delete':
diff --git a/core/modules/comment/lib/Drupal/comment/CommentFormController.php b/core/modules/comment/lib/Drupal/comment/CommentFormController.php
index d50605d..05d0f23 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentFormController.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentFormController.php
@@ -212,7 +212,7 @@ public function form(array $form, array &$form_state) {
     // Used for conditional validation of author fields.
     $form['is_anonymous'] = array(
       '#type' => 'value',
-      '#value' => ($comment->id() ? !$comment->uid->target_id : $this->currentUser->isAnonymous()),
+      '#value' => ($comment->id() ? !$comment->getAuthorId() : $this->currentUser->isAnonymous()),
     );
 
     // Add internal comment properties.
@@ -319,7 +319,7 @@ public function submit(array $form, array &$form_state) {
     // @todo Too fragile. Should be prepared and stored in comment_form()
     // already.
     if (!$comment->is_anonymous && !empty($comment->name->value) && ($account = user_load_by_name($comment->name->value))) {
-      $comment->uid->target_id = $account->id();
+      $comment->setAuthorId($account->id());
     }
     // If the comment was posted by an anonymous user and no author name was
     // required, use "Anonymous" by default.
diff --git a/core/modules/comment/lib/Drupal/comment/CommentInterface.php b/core/modules/comment/lib/Drupal/comment/CommentInterface.php
index fb9c043..6308f59 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentInterface.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentInterface.php
@@ -8,12 +8,13 @@
 namespace Drupal\comment;
 
 use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\user\EntityAuthorInterface;
 use Drupal\Core\Entity\EntityChangedInterface;
 
 /**
  * Provides an interface defining a comment entity.
  */
-interface CommentInterface extends ContentEntityInterface, EntityChangedInterface {
+interface CommentInterface extends ContentEntityInterface, EntityChangedInterface, EntityAuthorInterface {
 
   /**
    * Returns the permalink URL for this comment.
diff --git a/core/modules/comment/lib/Drupal/comment/CommentStorageController.php b/core/modules/comment/lib/Drupal/comment/CommentStorageController.php
index 751549f..b52828d 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentStorageController.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentStorageController.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\FieldableDatabaseStorageController;
 use Drupal\Core\Entity\EntityChangedInterface;
+use Drupal\user\EntityAuthorInterface;
 
 /**
  * Defines the controller class for comments.
@@ -97,6 +98,16 @@ public function updateEntityStatistics(CommentInterface $comment) {
     else {
       // Comments do not exist.
       $entity = entity_load($comment->entity_type->value, $comment->entity_id->value);
+      // Get the user ID from the entity if it's set, or default to the
+      // currently logged in user.
+      if ($entity instanceof EntityAuthorInterface) {
+        $last_comment_uid = $entity->getAuthorId();
+      }
+      if (!isset($last_comment_uid)) {
+        // Default to current user when entity does not implement
+        // EntityAuthorInterface or author is not set.
+        $last_comment_uid = \Drupal::currentUser()->id();
+      }
       $this->database->update('comment_entity_statistics')
         ->fields(array(
           'cid' => 0,
@@ -105,10 +116,7 @@ public function updateEntityStatistics(CommentInterface $comment) {
           // REQUEST_TIME.
           'last_comment_timestamp' => ($entity instanceof EntityChangedInterface) ? $entity->getChangedTime() : REQUEST_TIME,
           'last_comment_name' => '',
-          // @todo Use $entity->getAuthorId() after https://drupal.org/node/2078387
-          // Get the user ID from the entity if it's set, or default to the
-          // currently logged in user.
-          'last_comment_uid' => $entity->hasField('uid') ? $entity->get('uid')->value : \Drupal::currentUser()->id(),
+          'last_comment_uid' => $last_comment_uid,
         ))
         ->condition('entity_id', $comment->entity_id->value)
         ->condition('entity_type', $comment->entity_type->value)
diff --git a/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php b/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php
index 2713d52..101c604 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php
@@ -99,7 +99,7 @@ public function buildContent(array $entities, array $displays, $view_mode, $lang
     // Pre-load associated users into cache to leverage multiple loading.
     $uids = array();
     foreach ($entities as $entity) {
-      $uids[] = $entity->uid->target_id;
+      $uids[] = $entity->getAuthorId();
     }
     $this->entityManager->getStorageController('user')->loadMultiple(array_unique($uids));
 
diff --git a/core/modules/comment/lib/Drupal/comment/Entity/Comment.php b/core/modules/comment/lib/Drupal/comment/Entity/Comment.php
index cf96a59..98675be 100644
--- a/core/modules/comment/lib/Drupal/comment/Entity/Comment.php
+++ b/core/modules/comment/lib/Drupal/comment/Entity/Comment.php
@@ -13,6 +13,7 @@
 use Drupal\comment\CommentInterface;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\Core\Language\Language;
+use Drupal\user\UserInterface;
 
 /**
  * Defines the comment entity class.
@@ -288,7 +289,7 @@ public function preSave(EntityStorageControllerInterface $storage_controller) {
       }
       // We test the value with '===' because we need to modify anonymous
       // users as well.
-      if ($this->uid->target_id === $user->id() && $user->isAuthenticated()) {
+      if ($this->getAuthorId() === $user->id() && $user->isAuthenticated()) {
         $this->name->value = $user->getUsername();
       }
       // Add the values which aren't passed into the function.
@@ -471,4 +472,34 @@ public static function preCreate(EntityStorageControllerInterface $storage_contr
     }
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getAuthor() {
+    return $this->get('uid')->entity;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getAuthorId() {
+    return $this->get('uid')->target_id;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setAuthorId($uid) {
+    $this->set('uid', $uid);
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setAuthor(UserInterface $account) {
+    $this->set('uid', $account->id());
+    return $this;
+  }
+
 }
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentInterfaceTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentInterfaceTest.php
index b0311cb..f1b5a50 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentInterfaceTest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentInterfaceTest.php
@@ -78,7 +78,7 @@ function testCommentInterface() {
 
     // Test changing the comment author to "Anonymous".
     $comment = $this->postComment(NULL, $comment->comment_body->value, $comment->subject->value, array('name' => ''));
-    $this->assertTrue(empty($comment->name->value) && $comment->uid->target_id == 0, 'Comment author successfully changed to anonymous.');
+    $this->assertTrue(empty($comment->name->value) && $comment->getAuthorId() == 0, 'Comment author successfully changed to anonymous.');
 
     // Test changing the comment author to an unverified user.
     $random_name = $this->randomName();
@@ -90,7 +90,7 @@ function testCommentInterface() {
     // Test changing the comment author to a verified user.
     $this->drupalGet('comment/' . $comment->id() . '/edit');
     $comment = $this->postComment(NULL, $comment->comment_body->value, $comment->subject->value, array('name' => $this->web_user->getUsername()));
-    $this->assertTrue($comment->name->value == $this->web_user->getUsername() && $comment->uid->target_id == $this->web_user->id(), 'Comment author successfully changed to a registered user.');
+    $this->assertTrue($comment->name->value == $this->web_user->getUsername() && $comment->getAuthorId() == $this->web_user->id(), 'Comment author successfully changed to a registered user.');
 
     $this->drupalLogout();
 
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentTokenReplaceTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentTokenReplaceTest.php
index 7b9b9ff..0569ccf 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentTokenReplaceTest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentTokenReplaceTest.php
@@ -67,7 +67,7 @@ function testCommentTokenReplacement() {
     $tests['[comment:parent:title]'] = check_plain($parent_comment->subject->value);
     $tests['[comment:node:nid]'] = $comment->entity_id->value;
     $tests['[comment:node:title]'] = check_plain($node->getTitle());
-    $tests['[comment:author:uid]'] = $comment->uid->target_id;
+    $tests['[comment:author:uid]'] = $comment->getAuthorId();
     $tests['[comment:author:name]'] = check_plain($this->admin_user->getUsername());
 
     // Test to make sure that we generated something for each token.
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/Views/DefaultViewRecentComments.php b/core/modules/comment/lib/Drupal/comment/Tests/Views/DefaultViewRecentComments.php
index c2b59e2..cdd68e3 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/Views/DefaultViewRecentComments.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/Views/DefaultViewRecentComments.php
@@ -86,7 +86,7 @@ public function setUp() {
         'entity_type' => 'node',
         'entity_id' => $this->node->id(),
       ));
-      $comment->uid->target_id = 0;
+      $comment->setAuthorId(0);
       // Stagger the comments so the timestamp sorting works.
       $comment->created->value = REQUEST_TIME - $i;
       $comment->subject->value = 'Test comment ' . $i;
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Field/FieldWidget/AutocompleteWidgetBase.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Field/FieldWidget/AutocompleteWidgetBase.php
index 9880f32..628de24 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Field/FieldWidget/AutocompleteWidgetBase.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Field/FieldWidget/AutocompleteWidgetBase.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\Core\Field\WidgetBase;
+use Drupal\user\EntityAuthorInterface;
 use Symfony\Component\Validator\ConstraintViolationInterface;
 
 /**
@@ -94,8 +95,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
       '#size' => $this->getSetting('size'),
       '#placeholder' => $this->getSetting('placeholder'),
       '#element_validate' => array(array($this, 'elementValidate')),
-      // @todo: Use wrapper to get the user if exists or needed.
-      '#autocreate_uid' => isset($entity->uid) ? $entity->uid : $user->id(),
+      '#autocreate_uid' => ($entity instanceof EntityAuthorInterface) ? $entity->getAuthorId() : $user->id(),
     );
 
     return array('target_id' => $element);
@@ -172,11 +172,16 @@ protected function createNewEntity($label, $uid) {
     $bundle_key = $entity_info['entity_keys']['bundle'];
     $label_key = $entity_info['entity_keys']['label'];
 
-    return $entity_manager->getStorageController($target_type)->create(array(
+    $entity = $entity_manager->getStorageController($target_type)->create(array(
       $label_key => $label,
-      $bundle_key => $bundle,
-      'uid' => $uid,
+      $bundle_key => $bundle
     ));
+
+    if ($entity instanceof EntityAuthorInterface) {
+      $entity->setAuthorId($uid);
+    }
+
+    return $entity;
   }
 
   /**
diff --git a/core/modules/file/file.api.php b/core/modules/file/file.api.php
index 242e9ab..2030995 100644
--- a/core/modules/file/file.api.php
+++ b/core/modules/file/file.api.php
@@ -113,9 +113,9 @@ function hook_file_insert(Drupal\file\FileInterface $file) {
  */
 function hook_file_update(Drupal\file\FileInterface $file) {
   // Make sure that the file name starts with the owner's user name.
-  if (strpos($file->getFilename(), $file->getOwner()->name) !== 0) {
+  if (strpos($file->getFilename(), $file->getAuthor()->name) !== 0) {
     $old_filename = $file->getFilename();
-    $file->setFilename($file->getOwner()->name . '_' . $file->getFilename());
+    $file->setFilename($file->getAuthor()->name . '_' . $file->getFilename());
     $file->save();
 
     watchdog('file', t('%source has been renamed to %destination', array('%source' => $old_filename, '%destination' => $file->getFilename())));
@@ -134,8 +134,8 @@ function hook_file_update(Drupal\file\FileInterface $file) {
  */
 function hook_file_copy(Drupal\file\FileInterface $file, Drupal\file\FileInterface $source) {
   // Make sure that the file name starts with the owner's user name.
-  if (strpos($file->getFilename(), $file->getOwner()->name) !== 0) {
-    $file->setFilename($file->getOwner()->name . '_' . $file->getFilename());
+  if (strpos($file->getFilename(), $file->getAuthor()->name) !== 0) {
+    $file->setFilename($file->getAuthor()->name . '_' . $file->getFilename());
     $file->save();
 
     watchdog('file', t('Copied file %source has been renamed to %destination', array('%source' => $source->filename, '%destination' => $file->getFilename())));
@@ -154,8 +154,8 @@ function hook_file_copy(Drupal\file\FileInterface $file, Drupal\file\FileInterfa
  */
 function hook_file_move(Drupal\file\FileInterface $file, Drupal\file\FileInterface $source) {
   // Make sure that the file name starts with the owner's user name.
-  if (strpos($file->getFilename(), $file->getOwner()->name) !== 0) {
-    $file->setFilename($file->getOwner()->name . '_' . $file->getFilename());
+  if (strpos($file->getFilename(), $file->getAuthor()->name) !== 0) {
+    $file->setFilename($file->getAuthor()->name . '_' . $file->getFilename());
     $file->save();
 
     watchdog('file', t('Moved file %source has been renamed to %destination', array('%source' => $source->filename, '%destination' => $file->getFilename())));
diff --git a/core/modules/file/file.module b/core/modules/file/file.module
index 8ac1514..4b2d8c7 100644
--- a/core/modules/file/file.module
+++ b/core/modules/file/file.module
@@ -633,7 +633,7 @@ function file_file_download($uri, $field_type = 'file') {
   // temporary files where the host entity has not yet been saved (for example,
   // an image preview on a node/add form) in which case, allow download by the
   // file's owner.
-  if (empty($references) && ($file->isPermanent() || $file->getOwner()->id() != $user->id())) {
+  if (empty($references) && ($file->isPermanent() || $file->getAuthorId() != $user->id())) {
     return;
   }
 
@@ -1049,7 +1049,7 @@ function file_tokens($type, $tokens, array $data = array(), array $options = arr
           break;
 
         case 'owner':
-          $name = $file->getOwner()->label();
+          $name = $file->getAuthor()->label();
           $replacements[$original] = $sanitize ? check_plain($name) : $name;
           break;
       }
@@ -1059,8 +1059,8 @@ function file_tokens($type, $tokens, array $data = array(), array $options = arr
       $replacements += $token_service->generate('date', $date_tokens, array('date' => $file->getChangedTime()), $options);
     }
 
-    if (($owner_tokens = $token_service->findWithPrefix($tokens, 'owner')) && $file->getOwner()) {
-      $replacements += $token_service->generate('user', $owner_tokens, array('user' => $file->getOwner()), $options);
+    if (($owner_tokens = $token_service->findWithPrefix($tokens, 'owner')) && $file->getAuthor()) {
+      $replacements += $token_service->generate('user', $owner_tokens, array('user' => $file->getAuthor()), $options);
     }
   }
 
diff --git a/core/modules/file/lib/Drupal/file/Entity/File.php b/core/modules/file/lib/Drupal/file/Entity/File.php
index 3239cdf..bab7e74 100644
--- a/core/modules/file/lib/Drupal/file/Entity/File.php
+++ b/core/modules/file/lib/Drupal/file/Entity/File.php
@@ -119,15 +119,31 @@ public function getChangedTime() {
   /**
    * {@inheritdoc}
    */
-  public function getOwner() {
+  public function getAuthor() {
     return $this->get('uid')->entity;
   }
 
   /**
    * {@inheritdoc}
    */
-  public function setOwner(UserInterface $user) {
-    return $this->get('uid')->entity = $user;
+  public function getAuthorId() {
+    return $this->get('uid')->target_id;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setAuthorId($uid) {
+    $this->set('uid', $uid);
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setAuthor(UserInterface $account) {
+    $this->set('uid', $account->id());
+    return $this;
   }
 
   /**
diff --git a/core/modules/file/lib/Drupal/file/FileInterface.php b/core/modules/file/lib/Drupal/file/FileInterface.php
index 73783ef..1ae682e 100644
--- a/core/modules/file/lib/Drupal/file/FileInterface.php
+++ b/core/modules/file/lib/Drupal/file/FileInterface.php
@@ -8,13 +8,14 @@
 namespace Drupal\file;
 
 use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\user\EntityAuthorInterface;
 use Drupal\Core\Entity\EntityChangedInterface;
 use Drupal\user\UserInterface;
 
 /**
  * Defines getter and setter methods for file entity base fields.
  */
-interface FileInterface extends ContentEntityInterface, EntityChangedInterface {
+interface FileInterface extends ContentEntityInterface, EntityChangedInterface, EntityAuthorInterface {
 
   /**
    * Returns the name of the file.
@@ -111,20 +112,4 @@ public function setPermanent();
    */
   public function setTemporary();
 
-  /**
-   * Returns the user that owns this file.
-   *
-   * @return \Drupal\user\UserInterface
-   *   The user that owns the file.
-   */
-  public function getOwner();
-
-  /**
-   * Sets the user that owns this file.
-   *
-   * @param \Drupal\user\UserInterface $user
-   *   The user that owns the file.
-   */
-  public function setOwner(UserInterface $user);
-
 }
diff --git a/core/modules/file/lib/Drupal/file/Tests/FileTokenReplaceTest.php b/core/modules/file/lib/Drupal/file/Tests/FileTokenReplaceTest.php
index 924c2b9..fea281a 100644
--- a/core/modules/file/lib/Drupal/file/Tests/FileTokenReplaceTest.php
+++ b/core/modules/file/lib/Drupal/file/Tests/FileTokenReplaceTest.php
@@ -56,7 +56,7 @@ function testFileTokenReplacement() {
     $tests['[file:timestamp]'] = format_date($file->getChangedTime(), 'medium', '', NULL, $language_interface->id);
     $tests['[file:timestamp:short]'] = format_date($file->getChangedTime(), 'short', '', NULL, $language_interface->id);
     $tests['[file:owner]'] = check_plain(user_format_name($this->admin_user));
-    $tests['[file:owner:uid]'] = $file->getOwner()->id();
+    $tests['[file:owner:uid]'] = $file->getAuthorId();
 
     // Test to make sure that we generated something for each token.
     $this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated.');
diff --git a/core/modules/node/lib/Drupal/node/Entity/Node.php b/core/modules/node/lib/Drupal/node/Entity/Node.php
index 3700499..7147cd7 100644
--- a/core/modules/node/lib/Drupal/node/Entity/Node.php
+++ b/core/modules/node/lib/Drupal/node/Entity/Node.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Language\Language;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\node\NodeInterface;
+use Drupal\user\UserInterface;
 
 /**
  * Defines the node entity class.
@@ -296,6 +297,14 @@ public function setAuthorId($uid) {
   /**
    * {@inheritdoc}
    */
+  public function setAuthor(UserInterface $account) {
+    $this->set('uid', $account->id());
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function getRevisionCreationTime() {
     return $this->get('revision_timestamp')->value;
   }
diff --git a/core/modules/node/lib/Drupal/node/NodeInterface.php b/core/modules/node/lib/Drupal/node/NodeInterface.php
index 34f7274..9c7afb4 100644
--- a/core/modules/node/lib/Drupal/node/NodeInterface.php
+++ b/core/modules/node/lib/Drupal/node/NodeInterface.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\node;
 
+use Drupal\user\EntityAuthorInterface;
 use Drupal\Core\Entity\EntityChangedInterface;
 use Drupal\Core\Entity\ContentEntityInterface;
 use Drupal\user\UserInterface;
@@ -14,7 +15,7 @@
 /**
  * Provides an interface defining a node entity.
  */
-interface NodeInterface extends ContentEntityInterface, EntityChangedInterface {
+interface NodeInterface extends ContentEntityInterface, EntityChangedInterface, EntityAuthorInterface {
 
   /**
    * Returns the node type.
@@ -25,7 +26,6 @@
   public function getType();
 
   /**
-   *
    * Returns the node title.
    *
    * @return string
@@ -102,33 +102,6 @@ public function isSticky();
   public function setSticky($sticky);
 
   /**
-   * Returns the node author user entity.
-   *
-   * @return \Drupal\user\UserInterface
-   *   The author user entity.
-   */
-  public function getAuthor();
-
-  /**
-   * Returns the node author user ID.
-   *
-   * @return int
-   *   The author user ID.
-   */
-  public function getAuthorId();
-
-  /**
-   * Sets the node author user ID.
-   *
-   * @param int $uid
-   *   The author user id.
-   *
-   * @return \Drupal\node\NodeInterface
-   *   The called node entity.
-   */
-  public function setAuthorId($uid);
-
-  /**
    * Returns the node published status indicator.
    *
    * Unpublished nodes are only visible to their authors and to administrators.
@@ -160,7 +133,7 @@ public function getRevisionCreationTime();
   /**
    * Sets the node revision creation timestamp.
    *
-   * @param int $imestamp
+   * @param int $timestamp
    *   The UNIX timestamp of when this revision was created.
    *
    * @return \Drupal\node\NodeInterface
diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php
index b8a3bfb..32aeef3 100644
--- a/core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php
+++ b/core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php
@@ -275,8 +275,8 @@ function _testBasicCommentRdfaMarkup($graph, $comment, $account = array()) {
     $this->assertTrue($graph->hasProperty($comment_uri, 'http://purl.org/rss/1.0/modules/content/encoded', $expected_value), 'Comment body found in RDF output (content:encoded).');
 
     // The comment author can be a registered user or an anonymous user.
-    if ($comment->uid->value > 0) {
-      $author_uri = url('user/' . $comment->uid->value, array('absolute' => TRUE));
+    if ($comment->getAuthorId() > 0) {
+      $author_uri = url('user/' . $comment->getAuthorId(), array('absolute' => TRUE));
       // Comment relation to author.
       $expected_value = array(
         'type' => 'uri',
@@ -304,7 +304,7 @@ function _testBasicCommentRdfaMarkup($graph, $comment, $account = array()) {
     $this->assertTrue($graph->hasProperty($author_uri, 'http://xmlns.com/foaf/0.1/name', $expected_value), 'Comment author name found in RDF output (foaf:name).');
 
     // Comment author homepage (only for anonymous authors).
-    if ($comment->uid->value == 0) {
+    if ($comment->getAuthorId() == 0) {
       $expected_value = array(
         'type' => 'uri',
         'value' => 'http://example.org/',
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/FileTestBase.php b/core/modules/system/lib/Drupal/system/Tests/File/FileTestBase.php
index 540c19a..221c547 100644
--- a/core/modules/system/lib/Drupal/system/Tests/File/FileTestBase.php
+++ b/core/modules/system/lib/Drupal/system/Tests/File/FileTestBase.php
@@ -37,7 +37,7 @@ function setUp() {
    */
   function assertFileUnchanged(FileInterface $before, FileInterface $after) {
     $this->assertEqual($before->id(), $after->id(), t('File id is the same: %file1 == %file2.', array('%file1' => $before->id(), '%file2' => $after->id())), 'File unchanged');
-    $this->assertEqual($before->getOwner()->id(), $after->getOwner()->id(), t('File owner is the same: %file1 == %file2.', array('%file1' => $before->getOwner()->id(), '%file2' => $after->getOwner()->id())), 'File unchanged');
+    $this->assertEqual($before->getAuthorId(), $after->getAuthorId(), t('File owner is the same: %file1 == %file2.', array('%file1' => $before->getAuthorId(), '%file2' => $after->getAuthorId())), 'File unchanged');
     $this->assertEqual($before->getFilename(), $after->getFilename(), t('File name is the same: %file1 == %file2.', array('%file1' => $before->getFilename(), '%file2' => $after->getFilename())), 'File unchanged');
     $this->assertEqual($before->getFileUri(), $after->getFileUri(), t('File path is the same: %file1 == %file2.', array('%file1' => $before->getFileUri(), '%file2' => $after->getFileUri())), 'File unchanged');
     $this->assertEqual($before->getMimeType(), $after->getMimeType(), t('File MIME type is the same: %file1 == %file2.', array('%file1' => $before->getMimeType(), '%file2' => $after->getMimeType())), 'File unchanged');
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php
index b4ad49b..e0d5967 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php
@@ -10,7 +10,9 @@
 use Drupal\Core\Entity\ContentEntityBase;
 use Drupal\Core\Entity\Annotation\EntityType;
 use Drupal\Core\Annotation\Translation;
+use Drupal\user\EntityAuthorInterface;
 use Drupal\Core\Language\Language;
+use Drupal\user\UserInterface;
 
 /**
  * Defines the test entity class.
@@ -44,7 +46,7 @@
  *   }
  * )
  */
-class EntityTest extends ContentEntityBase {
+class EntityTest extends ContentEntityBase implements EntityAuthorInterface {
 
   /**
    * The entity ID.
@@ -155,4 +157,35 @@ public static function baseFieldDefinitions($entity_type) {
     );
     return $fields;
   }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getAuthor() {
+    return $this->get('user_id')->entity;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getAuthorId() {
+    return $this->get('user_id')->target_id;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setAuthorId($uid) {
+    $this->set('user_id', $uid);
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setAuthor(UserInterface $account) {
+    $this->set('uid', $account->id());
+    return $this;
+  }
+
 }
diff --git a/core/modules/tracker/tracker.module b/core/modules/tracker/tracker.module
index 878a755..9f4dceb 100644
--- a/core/modules/tracker/tracker.module
+++ b/core/modules/tracker/tracker.module
@@ -194,7 +194,7 @@ function tracker_comment_update($comment) {
   // $comment->save() calls hook_comment_publish() for all published comments
   // so we need to handle all other values here.
   if ($comment->status->value != COMMENT_PUBLISHED && $comment->entity_type->value == 'node') {
-    _tracker_remove($comment->entity_id->target_id, $comment->uid->target_id, $comment->changed->value);
+    _tracker_remove($comment->entity_id->target_id, $comment->getAuthorId(), $comment->changed->value);
   }
 }
 
@@ -206,7 +206,7 @@ function tracker_comment_update($comment) {
  */
 function tracker_comment_publish($comment) {
   if ($comment->entity_type->value == 'node') {
-    _tracker_add($comment->entity_id->target_id, $comment->uid->target_id, $comment->changed->value);
+    _tracker_add($comment->entity_id->target_id, $comment->getAuthorId(), $comment->changed->value);
   }
 }
 
@@ -215,7 +215,7 @@ function tracker_comment_publish($comment) {
  */
 function tracker_comment_unpublish($comment) {
   if ($comment->entity_type->value == 'node') {
-    _tracker_remove($comment->entity_id->target_id, $comment->uid->target_id, $comment->changed->value);
+    _tracker_remove($comment->entity_id->target_id, $comment->getAuthorId(), $comment->changed->value);
   }
 }
 
@@ -224,7 +224,7 @@ function tracker_comment_unpublish($comment) {
  */
 function tracker_comment_delete($comment) {
   if ($comment->entity_type->value == 'node') {
-    _tracker_remove($comment->entity_id->target_id, $comment->uid->target_id, $comment->changed->value);
+    _tracker_remove($comment->entity_id->target_id, $comment->getAuthorId(), $comment->changed->value);
   }
 }
 
diff --git a/core/modules/user/lib/Drupal/user/EntityAuthorInterface.php b/core/modules/user/lib/Drupal/user/EntityAuthorInterface.php
new file mode 100644
index 0000000..63a00f3
--- /dev/null
+++ b/core/modules/user/lib/Drupal/user/EntityAuthorInterface.php
@@ -0,0 +1,53 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\user\EntityAuthorInterface.
+ */
+
+namespace Drupal\user;
+
+/**
+ * Defines a common interface for entities that have an author or owner.
+ */
+interface EntityAuthorInterface {
+
+  /**
+   * Returns the entity author's user entity.
+   *
+   * @return \Drupal\user\UserInterface
+   *   The author user entity.
+   */
+  public function getAuthor();
+
+  /**
+   * Returns the entity author's user entity.
+   *
+   * @param \Drupal\user\UserInterface $account
+   *   The author user entity.
+   *
+   * @return self
+   *   The called entity.
+   */
+  public function setAuthor(UserInterface $account);
+
+  /**
+   * Returns the entity author's user ID.
+   *
+   * @return int
+   *   The author user ID.
+   */
+  public function getAuthorId();
+
+  /**
+   * Sets the entity author's user ID.
+   *
+   * @param int $uid
+   *   The author user id.
+   *
+   * @return self
+   *   The called entity.
+   */
+  public function setAuthorId($uid);
+
+}
